CookBook/FirstSteps.thy
changeset 131 8db9195bb3e9
parent 128 693711a0c702
child 132 2d9198bcb850
equal deleted inserted replaced
130:a21d7b300616 131:8db9195bb3e9
   169 
   169 
   170 
   170 
   171 section {* Combinators\label{sec:combinators} *}
   171 section {* Combinators\label{sec:combinators} *}
   172 
   172 
   173 text {*
   173 text {*
   174   For beginners, perhaps the most puzzling parts in the existing code of Isabelle are
   174   For beginners perhaps the most puzzling parts in the existing code of Isabelle are
   175   the combinators. At first they seem to greatly obstruct the
   175   the combinators. At first they seem to greatly obstruct the
   176   comprehension of the code, but after getting familiar with them, they
   176   comprehension of the code, but after getting familiar with them, they
   177   actually ease the understanding and also the programming.
   177   actually ease the understanding and also the programming.
   178 
   178 
   179   The simplest combinator is @{ML I}, which is just the identity function defined as
   179   The simplest combinator is @{ML I}, which is just the identity function defined as
   211   the first component of the pair (Line 4) and finally incrementing the first 
   211   the first component of the pair (Line 4) and finally incrementing the first 
   212   component by 4 (Line 5). This kind of cascading manipulations of values is quite
   212   component by 4 (Line 5). This kind of cascading manipulations of values is quite
   213   common when dealing with theories (for example by adding a definition, followed by
   213   common when dealing with theories (for example by adding a definition, followed by
   214   lemmas and so on). The reverse application allows you to read what happens in 
   214   lemmas and so on). The reverse application allows you to read what happens in 
   215   a top-down manner. This kind of coding should also be familiar, 
   215   a top-down manner. This kind of coding should also be familiar, 
   216   if you used Haskell's do-notation. Writing the function @{ML inc_by_five} using 
   216   if you used to Haskell's do-notation. Writing the function @{ML inc_by_five} using 
   217   the reverse application is much clearer than writing
   217   the reverse application is much clearer than writing
   218 *}
   218 *}
   219 
   219 
   220 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*}
   220 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*}
   221 
   221 
   378 
   378 
   379   In a similar way you can use antiquotations to refer to proved theorems:
   379   In a similar way you can use antiquotations to refer to proved theorems:
   380 
   380 
   381   @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"}
   381   @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"}
   382 
   382 
   383   and current simpsets:
   383   and current simpsets. For this we use the function that extracts the 
   384 
   384   theorem names stored in the simpset.
   385   @{ML_response_fake [display,gray] 
   385 *}
   386 "let
   386 
   387   val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset}
   387 ML{*fun get_thm_names simpset =
       
   388 let
       
   389   val ({rules,...}, _) = MetaSimplifier.rep_ss simpset
   388 in
   390 in
   389   map #name (Net.entries rules)
   391   map #name (Net.entries rules)
   390 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   392 end*}
   391 
   393 
   392   The code about simpsets extracts the theorem names stored in the
   394 text {*
   393   simpset.  You can get hold of the current simpset with the antiquotation 
   395   The function @{ML rep_ss in MetaSimplifier} returns a record containing all
   394   @{text "@{simpset}"}.  The function @{ML rep_ss in MetaSimplifier} returns a record
   396   information about the simpset. The rules of a simpset are stored in a
   395   containing all information about the simpset. The rules of a simpset are
   397   \emph{discrimination net} (a data structure for fast indexing). From this
   396   stored in a \emph{discrimination net} (a data structure for fast
   398   net you can extract the entries using the function @{ML Net.entries}.
   397   indexing). From this net you can extract the entries using the function @{ML
   399   You can now use @{ML get_thm_names} to obtain all names of theorems of
   398   Net.entries}.
   400   the current simpset using the antiquotation @{text "@{simpset}"}.\footnote
   399 
   401   {FIXME: you cannot cleanly match against lists with ommited parts}
       
   402 
       
   403   @{ML_response_fake [display,gray] 
       
   404 "get_thm_names @{simpset}" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   400 
   405 
   401   \begin{readmore}
   406   \begin{readmore}
   402   The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"}
   407   The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"}
   403   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   408   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   404   in @{ML_file "Pure/net.ML"}.
   409   in @{ML_file "Pure/net.ML"}.
   509   written as:
   514   written as:
   510 
   515 
   511 *}
   516 *}
   512 
   517 
   513 ML{*fun make_imp P Q tau =
   518 ML{*fun make_imp P Q tau =
   514   let
   519 let
   515     val x = Free ("x",tau)
   520   val x = Free ("x",tau)
   516   in 
   521 in 
   517     Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   522   Logic.all x (Logic.mk_implies (P $ x, Q $ x))
   518   end *}
   523 end *}
   519 
   524 
   520 text {*
   525 text {*
   521   The reason is that you cannot pass the arguments @{term P}, @{term Q} and 
   526   The reason is that you cannot pass the arguments @{term P}, @{term Q} and 
   522   @{term "tau"} into an antiquotation. For example the following does \emph{not} work.
   527   @{term "tau"} into an antiquotation. For example the following does \emph{not} work.
   523 *}
   528 *}
   601 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
   606 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
   602            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
   607            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
   603 
   608 
   604 
   609 
   605   There are a few subtle issues with constants. They usually crop up when
   610   There are a few subtle issues with constants. They usually crop up when
   606   pattern matching terms or constructing terms. While it is perfectly ok
   611   pattern matching terms or types, or constructing them. While it is perfectly ok
   607   to write the function @{text is_true} as follows
   612   to write the function @{text is_true} as follows
   608 *}
   613 *}
   609 
   614 
   610 ML{*fun is_true @{term True} = true
   615 ML{*fun is_true @{term True} = true
   611   | is_true _ = false*}
   616   | is_true _ = false*}
   635 text {* 
   640 text {* 
   636   because now
   641   because now
   637 
   642 
   638 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"}
   643 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"}
   639 
   644 
   640   matches correctly (the wildcard in the pattern matches any type).
   645   matches correctly (the first wildcard in the pattern matches any type).
   641 
   646 
   642   However there is still a problem: consider the similar function that
   647   However there is still a problem: consider the similar function that
   643   attempts to pick out a @{text "Nil"}-term:
   648   attempts to pick out @{text "Nil"}-terms:
   644 *}
   649 *}
   645 
   650 
   646 ML{*fun is_nil (Const ("Nil", _)) = true
   651 ML{*fun is_nil (Const ("Nil", _)) = true
   647   | is_nil _ = false *}
   652   | is_nil _ = false *}
   648 
   653 
   656   because @{term "All"} is such a fundamental constant, which can be referenced
   661   because @{term "All"} is such a fundamental constant, which can be referenced
   657   by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at
   662   by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at
   658 
   663 
   659   @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"}
   664   @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"}
   660 
   665 
   661   the name of the constant @{term "Nil"} depends on the theory in which the
   666   the name of the constant @{text "Nil"} depends on the theory in which the
   662   term constructor is defined (@{text "List"}) and also in which datatype
   667   term constructor is defined (@{text "List"}) and also in which datatype
   663   (@{text "list"}). Even worse, some constants have a name involving
   668   (@{text "list"}). Even worse, some constants have a name involving
   664   type-classes. Consider for example the constants for @{term "zero"} and
   669   type-classes. Consider for example the constants for @{term "zero"} and
   665   @{text "(op *)"}:
   670   \mbox{@{text "(op *)"}}:
   666 
   671 
   667   @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" 
   672   @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" 
   668  "(Const (\"HOL.zero_class.zero\", \<dots>), 
   673  "(Const (\"HOL.zero_class.zero\", \<dots>), 
   669  Const (\"HOL.times_class.times\", \<dots>))"}
   674  Const (\"HOL.times_class.times\", \<dots>))"}
   670 
   675 
   682 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true
   687 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true
   683   | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true
   688   | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true
   684   | is_nil_or_all _ = false *}
   689   | is_nil_or_all _ = false *}
   685 
   690 
   686 text {*
   691 text {*
   687   Note that you occasional have to calculate what the ``base'' name of a given
   692   Occasional you have to calculate what the ``base'' name of a given
   688   constant is. For this you can use the function @{ML Sign.extern_const} or
   693   constant is. For this you can use the function @{ML Sign.extern_const} or
   689   @{ML Sign.base_name}. For example:
   694   @{ML Sign.base_name}. For example:
   690 
   695 
   691   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
   696   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
   692 
   697 
   693   The difference between both functions is that @{ML extern_const in Sign} returns
   698   The difference between both functions is that @{ML extern_const in Sign} returns
   694   the smallest name that is still unique, whereas @{ML base_name in Sign} always
   699   the smallest name that is still unique, whereas @{ML base_name in Sign} always
   695   strips off all qualifiers.
   700   strips off all qualifiers.
   696 
   701 
   697   (FIXME authentic syntax on the ML-level)
       
   698 
       
   699   \begin{readmore}
   702   \begin{readmore}
   700   FIXME
   703   FIXME
   701   \end{readmore}
   704   \end{readmore}
   702 *}
   705 *}
   703 
   706 
   704 
   707 
   705 section {* Type-Checking *}
   708 section {* Type-Checking *}
   706 
   709 
   707 text {* 
   710 text {* 
   708   
   711   
   709   You can freely construct and manipulate @{ML_type "term"}s, since they are just
   712   You can freely construct and manipulate @{ML_type "term"}s and @{ML_type
   710   arbitrary unchecked trees. However, you eventually want to see if a
   713   typ}es, since they are just arbitrary unchecked trees. However, you
   711   term is well-formed, or type-checks, relative to a theory.
   714   eventually want to see if a term is well-formed, or type-checks, relative to
   712   Type-checking is done via the function @{ML cterm_of}, which converts 
   715   a theory.  Type-checking is done via the function @{ML cterm_of}, which
   713   a @{ML_type term} into a  @{ML_type cterm}, a \emph{certified} term. 
   716   converts a @{ML_type term} into a @{ML_type cterm}, a \emph{certified}
   714   Unlike @{ML_type term}s, which are just trees, @{ML_type
   717   term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are
   715   "cterm"}s are abstract objects that are guaranteed to be
   718   abstract objects that are guaranteed to be type-correct, and they can only
   716   type-correct, and they can only be constructed via ``official
   719   be constructed via ``official interfaces''.
   717   interfaces''.
   720 
   718 
   721 
   719   Type-checking is always relative to a theory context. For now we use
   722   Type-checking is always relative to a theory context. For now we use
   720   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   723   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   721   For example you can write:
   724   For example you can write:
   722 
   725 
   763   @{ML_response_fake [display,gray] 
   766   @{ML_response_fake [display,gray] 
   764   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
   767   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
   765   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
   768   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
   766 
   769 
   767   Since the complete traversal might sometimes be too costly and
   770   Since the complete traversal might sometimes be too costly and
   768   not necessary, there is also the function @{ML fastype_of} which 
   771   not necessary, there is also the function @{ML fastype_of}, which 
   769   returns the type of a term.
   772   returns the type of a term.
   770 
   773 
   771   @{ML_response [display,gray] 
   774   @{ML_response [display,gray] 
   772   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   775   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   773 
   776 
   796 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $
   799 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $
   797   Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"}
   800   Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"}
   798 
   801 
   799   Instead of giving explicitly the type for the constant @{text "plus"} and the free 
   802   Instead of giving explicitly the type for the constant @{text "plus"} and the free 
   800   variable @{text "x"}, the type-inference filled in the missing information.
   803   variable @{text "x"}, the type-inference filled in the missing information.
   801 
       
   802 
   804 
   803   \begin{readmore}
   805   \begin{readmore}
   804   See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading,
   806   See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading,
   805   checking and pretty-printing of terms are defined.
   807   checking and pretty-printing of terms are defined.
   806   \end{readmore}
   808   \end{readmore}