CookBook/FirstSteps.thy
changeset 149 253ea99c1441
parent 138 e4d8dfb7e34a
child 151 7e0bf13bf743
equal deleted inserted replaced
148:84d1392186d3 149:253ea99c1441
   139 
   139 
   140 ML{*fun str_of_cterm ctxt t =  
   140 ML{*fun str_of_cterm ctxt t =  
   141    Syntax.string_of_term ctxt (term_of t)*}
   141    Syntax.string_of_term ctxt (term_of t)*}
   142 
   142 
   143 text {*
   143 text {*
   144   The function @{ML term_of} extracts the @{ML_type term} from a @{ML_type cterm}.
   144   In this example the function @{ML term_of} extracts the @{ML_type term} from
   145   If there are more than one @{ML_type cterm}s to be printed, you can use the 
   145   a @{ML_type cterm}.  If there are more than one @{ML_type cterm}s to be
   146   function @{ML commas} to separate them.
   146   printed, you can use the function @{ML commas} to separate them.
   147 *} 
   147 *} 
   148 
   148 
   149 ML{*fun str_of_cterms ctxt ts =  
   149 ML{*fun str_of_cterms ctxt ts =  
   150    commas (map (str_of_cterm ctxt) ts)*}
   150    commas (map (str_of_cterm ctxt) ts)*}
   151 
   151 
   212   the first component of the pair (Line 4) and finally incrementing the first 
   212   the first component of the pair (Line 4) and finally incrementing the first 
   213   component by 4 (Line 5). This kind of cascading manipulations of values is quite
   213   component by 4 (Line 5). This kind of cascading manipulations of values is quite
   214   common when dealing with theories (for example by adding a definition, followed by
   214   common when dealing with theories (for example by adding a definition, followed by
   215   lemmas and so on). The reverse application allows you to read what happens in 
   215   lemmas and so on). The reverse application allows you to read what happens in 
   216   a top-down manner. This kind of coding should also be familiar, 
   216   a top-down manner. This kind of coding should also be familiar, 
   217   if you used to Haskell's do-notation. Writing the function @{ML inc_by_five} using 
   217   if you have been exposed to Haskell's do-notation. Writing the function @{ML inc_by_five} using 
   218   the reverse application is much clearer than writing
   218   the reverse application is much clearer than writing
   219 *}
   219 *}
   220 
   220 
   221 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*}
   221 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*}
   222 
   222 
   387 @{ML_response_fake [display,gray] "@{thms conj_ac}" 
   387 @{ML_response_fake [display,gray] "@{thms conj_ac}" 
   388 "(?P \<and> ?Q) = (?Q \<and> ?P)
   388 "(?P \<and> ?Q) = (?Q \<and> ?P)
   389 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R)
   389 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R)
   390 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"}  
   390 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"}  
   391 
   391 
   392   You can also refer to the current simpset. To illustrate this we use the
   392   You can also refer to the current simpset. To illustrate this we implement the
   393   function that extracts the theorem names stored in a simpset.
   393   function that extracts the theorem names stored in a simpset.
   394 *}
   394 *}
   395 
   395 
   396 ML{*fun get_thm_names simpset =
   396 ML{*fun get_thm_names_from_ss simpset =
   397 let
   397 let
   398   val ({rules,...}, _) = MetaSimplifier.rep_ss simpset
   398   val ({rules,...}, _) = MetaSimplifier.rep_ss simpset
   399 in
   399 in
   400   map #name (Net.entries rules)
   400   map #name (Net.entries rules)
   401 end*}
   401 end*}
   403 text {*
   403 text {*
   404   The function @{ML rep_ss in MetaSimplifier} returns a record containing all
   404   The function @{ML rep_ss in MetaSimplifier} returns a record containing all
   405   information about the simpset. The rules of a simpset are stored in a
   405   information about the simpset. The rules of a simpset are stored in a
   406   \emph{discrimination net} (a data structure for fast indexing). From this
   406   \emph{discrimination net} (a data structure for fast indexing). From this
   407   net you can extract the entries using the function @{ML Net.entries}.
   407   net you can extract the entries using the function @{ML Net.entries}.
   408   You can now use @{ML get_thm_names} to obtain all names of theorems stored
   408   You can now use @{ML get_thm_names_from_ss} to obtain all names of theorems stored
   409   in the current simpset---this simpset can be referred to using the antiquotation
   409   in the current simpset---this simpset can be referred to using the antiquotation
   410   @{text "@{simpset}"}.\footnote
   410   @{text "@{simpset}"}.
   411   {FIXME: you cannot cleanly match against lists with ommited parts}
       
   412 
   411 
   413   @{ML_response_fake [display,gray] 
   412   @{ML_response_fake [display,gray] 
   414 "get_thm_names @{simpset}" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   413   "get_thm_names_from_ss @{simpset}" 
       
   414   "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   415 
   415 
   416   \begin{readmore}
   416   \begin{readmore}
   417   The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"}
   417   The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"}
   418   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   418   and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented
   419   in @{ML_file "Pure/net.ML"}.
   419   in @{ML_file "Pure/net.ML"}.
   429   These bindings are difficult to maintain and also can be accidentally
   429   These bindings are difficult to maintain and also can be accidentally
   430   overwritten by the user. This often breakes Isabelle
   430   overwritten by the user. This often breakes Isabelle
   431   packages. Antiquotations solve this problem, since they are ``linked''
   431   packages. Antiquotations solve this problem, since they are ``linked''
   432   statically at compile-time.  However, this static linkage also limits their
   432   statically at compile-time.  However, this static linkage also limits their
   433   usefulness in cases where data needs to be build up dynamically. In the
   433   usefulness in cases where data needs to be build up dynamically. In the
   434   course of this introduction, you will learn more about these antiquotations:
   434   course of this chapter you will learn more about these antiquotations:
   435   they can simplify Isabelle programming since one can directly access all
   435   they can simplify Isabelle programming since one can directly access all
   436   kinds of logical elements from th ML-level.
   436   kinds of logical elements from th ML-level.
   437 
   437 
   438 *}
   438 *}
   439 
   439 
   444   \mbox{@{text "@{term \<dots>}"}}. For example:
   444   \mbox{@{text "@{term \<dots>}"}}. For example:
   445 
   445 
   446   @{ML_response [display,gray] 
   446   @{ML_response [display,gray] 
   447 "@{term \"(a::nat) + b = c\"}" 
   447 "@{term \"(a::nat) + b = c\"}" 
   448 "Const (\"op =\", \<dots>) $ 
   448 "Const (\"op =\", \<dots>) $ 
   449    (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   449   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   450 
   450 
   451   This will show the term @{term "(a::nat) + b = c"}, but printed using the internal
   451   This will show the term @{term "(a::nat) + b = c"}, but printed using the internal
   452   representation of this term. This internal representation corresponds to the 
   452   representation of this term. This internal representation corresponds to the 
   453   datatype @{ML_type "term"}.
   453   datatype @{ML_type "term"}.
   454   
   454   
   455   The internal representation of terms uses the usual de Bruijn index mechanism where bound 
   455   The internal representation of terms uses the usual de Bruijn index mechanism where bound 
   456   variables are represented by the constructor @{ML Bound}. The index in @{ML Bound} refers to
   456   variables are represented by the constructor @{ML Bound}. The index in @{ML Bound} refers to
   457   the number of Abstractions (@{ML Abs}) we have to skip until we hit the @{ML Abs} that
   457   the number of Abstractions (@{ML Abs}) we have to skip until we hit the @{ML Abs} that
   458   binds the corresponding variable. However, in Isabelle the names of bound variables are 
   458   binds the corresponding variable. However, in Isabelle the names of bound variables are 
   459   kept at abstractions for printing purposes, and so should be treated only as comments. 
   459   kept at abstractions for printing purposes, and so should be treated only as ``comments''. 
   460   Application in Isabelle is realised with the term-constructor @{ML $}.
   460   Application in Isabelle is realised with the term-constructor @{ML $}.
   461 
   461 
   462   \begin{readmore}
   462   \begin{readmore}
   463   Terms are described in detail in \isccite{sec:terms}. Their
   463   Terms are described in detail in \isccite{sec:terms}. Their
   464   definition and many useful operations are implemented in @{ML_file "Pure/term.ML"}.
   464   definition and many useful operations are implemented in @{ML_file "Pure/term.ML"}.
   490   inserting the invisible @{text "Trueprop"}-coercions whenever necessary. 
   490   inserting the invisible @{text "Trueprop"}-coercions whenever necessary. 
   491   Consider for example the pairs
   491   Consider for example the pairs
   492 
   492 
   493 @{ML_response [display,gray] "(@{term \"P x\"}, @{prop \"P x\"})" 
   493 @{ML_response [display,gray] "(@{term \"P x\"}, @{prop \"P x\"})" 
   494 "(Free (\"P\", \<dots>) $ Free (\"x\", \<dots>),
   494 "(Free (\"P\", \<dots>) $ Free (\"x\", \<dots>),
   495   Const (\"Trueprop\", \<dots>) $ (Free (\"P\", \<dots>) $ Free (\"x\", \<dots>)))"}
   495  Const (\"Trueprop\", \<dots>) $ (Free (\"P\", \<dots>) $ Free (\"x\", \<dots>)))"}
   496  
   496  
   497   where a coercion is inserted in the second component and 
   497   where a coercion is inserted in the second component and 
   498 
   498 
   499   @{ML_response [display,gray] "(@{term \"P x \<Longrightarrow> Q x\"}, @{prop \"P x \<Longrightarrow> Q x\"})" 
   499   @{ML_response [display,gray] "(@{term \"P x \<Longrightarrow> Q x\"}, @{prop \"P x \<Longrightarrow> Q x\"})" 
   500   "(Const (\"==>\", \<dots>) $ \<dots> $ \<dots>, Const (\"==>\", \<dots>) $ \<dots> $ \<dots>)"}
   500   "(Const (\"==>\", \<dots>) $ \<dots> $ \<dots>, Const (\"==>\", \<dots>) $ \<dots> $ \<dots>)"}
   615   in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the
   615   in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the
   616   number representing their sum.
   616   number representing their sum.
   617   \end{exercise}
   617   \end{exercise}
   618 
   618 
   619   There are a few subtle issues with constants. They usually crop up when
   619   There are a few subtle issues with constants. They usually crop up when
   620   pattern matching terms or types, or constructing them. While it is perfectly ok
   620   pattern matching terms or types, or when constructing them. While it is perfectly ok
   621   to write the function @{text is_true} as follows
   621   to write the function @{text is_true} as follows
   622 *}
   622 *}
   623 
   623 
   624 ML{*fun is_true @{term True} = true
   624 ML{*fun is_true @{term True} = true
   625   | is_true _ = false*}
   625   | is_true _ = false*}
   649 text {* 
   649 text {* 
   650   because now
   650   because now
   651 
   651 
   652 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"}
   652 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"}
   653 
   653 
   654   matches correctly (the first wildcard in the pattern matches any type).
   654   matches correctly (the first wildcard in the pattern matches any type and the
       
   655   second any term).
   655 
   656 
   656   However there is still a problem: consider the similar function that
   657   However there is still a problem: consider the similar function that
   657   attempts to pick out @{text "Nil"}-terms:
   658   attempts to pick out @{text "Nil"}-terms:
   658 *}
   659 *}
   659 
   660 
   664   Unfortunately, also this function does \emph{not} work as expected, since
   665   Unfortunately, also this function does \emph{not} work as expected, since
   665 
   666 
   666   @{ML_response [display,gray] "is_nil @{term \"Nil\"}" "false"}
   667   @{ML_response [display,gray] "is_nil @{term \"Nil\"}" "false"}
   667 
   668 
   668   The problem is that on the ML-level the name of a constant is more
   669   The problem is that on the ML-level the name of a constant is more
   669   subtle as you might expect. The function @{ML is_all} worked correctly,
   670   subtle than you might expect. The function @{ML is_all} worked correctly,
   670   because @{term "All"} is such a fundamental constant, which can be referenced
   671   because @{term "All"} is such a fundamental constant, which can be referenced
   671   by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at
   672   by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at
   672 
   673 
   673   @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"}
   674   @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"}
   674 
   675 
   730 
   731 
   731   Type-checking is always relative to a theory context. For now we use
   732   Type-checking is always relative to a theory context. For now we use
   732   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   733   the @{ML "@{theory}"} antiquotation to get hold of the current theory.
   733   For example you can write:
   734   For example you can write:
   734 
   735 
   735   @{ML_response_fake [display,gray] "cterm_of @{theory} @{term \"a + b = c\"}" "a + b = c"}
   736   @{ML_response_fake [display,gray] "cterm_of @{theory} @{term \"(a::nat) + b = c\"}" "a + b = c"}
   736 
   737 
   737   This can also be written with an antiquotation:
   738   This can also be written with an antiquotation:
   738 
   739 
   739   @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"}
   740   @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"}
   740 
   741 
   768   @{ML_response [display,gray] 
   769   @{ML_response [display,gray] 
   769   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   770   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   770 
   771 
   771   To calculate the type, this function traverses the whole term and will
   772   To calculate the type, this function traverses the whole term and will
   772   detect any typing inconsistency. For examle changing the type of the variable 
   773   detect any typing inconsistency. For examle changing the type of the variable 
   773   from @{typ "nat"} to @{typ "int"} will result in the error message: 
   774   @{term "x"} from @{typ "nat"} to @{typ "int"} will result in the error message: 
   774 
   775 
   775   @{ML_response_fake [display,gray] 
   776   @{ML_response_fake [display,gray] 
   776   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
   777   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
   777   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
   778   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
   778 
   779 
   779   Since the complete traversal might sometimes be too costly and
   780   Since the complete traversal might sometimes be too costly and
   780   not necessary, there is also the function @{ML fastype_of}, which 
   781   not necessary, there is the function @{ML fastype_of}, which 
   781   returns the type of a term.
   782   also returns the type of a term.
   782 
   783 
   783   @{ML_response [display,gray] 
   784   @{ML_response [display,gray] 
   784   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   785   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
   785 
   786 
   786   However, efficiency is gained on the expense of skiping some tests. You 
   787   However, efficiency is gained on the expense of skiping some tests. You 
   787   can see this in the following example
   788   can see this in the following example
   788 
   789 
   789    @{ML_response [display,gray] 
   790    @{ML_response [display,gray] 
   790   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" "bool"}
   791   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" "bool"}
   791 
   792 
   792   where no error is raised.
   793   where no error is detected.
   793 
   794 
   794   Sometimes it is a bit inconvenient to construct a term with 
   795   Sometimes it is a bit inconvenient to construct a term with 
   795   complete typing annotations, especially in cases where the typing 
   796   complete typing annotations, especially in cases where the typing 
   796   information is redundant. A short-cut is to use the ``place-holder'' 
   797   information is redundant. A short-cut is to use the ``place-holder'' 
   797   type @{ML "dummyT"} and then let type-inference figure out the 
   798   type @{ML "dummyT"} and then let type-inference figure out the 
   807 end"
   808 end"
   808 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $
   809 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $
   809   Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"}
   810   Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"}
   810 
   811 
   811   Instead of giving explicitly the type for the constant @{text "plus"} and the free 
   812   Instead of giving explicitly the type for the constant @{text "plus"} and the free 
   812   variable @{text "x"}, the type-inference filled in the missing information.
   813   variable @{text "x"}, the type-inference filles in the missing information.
   813 
   814 
   814   \begin{readmore}
   815   \begin{readmore}
   815   See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading,
   816   See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading,
   816   checking and pretty-printing of terms are defined.
   817   checking and pretty-printing of terms are defined.
   817   \end{readmore}
   818   \end{readmore}
   840   The corresponding ML-code is as follows:\footnote{Note that @{text "|>"} is reverse
   841   The corresponding ML-code is as follows:\footnote{Note that @{text "|>"} is reverse
   841   application. See Section~\ref{sec:combinators}.}
   842   application. See Section~\ref{sec:combinators}.}
   842 
   843 
   843 @{ML_response_fake [display,gray]
   844 @{ML_response_fake [display,gray]
   844 "let
   845 "let
   845 
       
   846   val assm1 = @{cprop \"\<And>(x::nat). P x \<Longrightarrow> Q x\"}
   846   val assm1 = @{cprop \"\<And>(x::nat). P x \<Longrightarrow> Q x\"}
   847   val assm2 = @{cprop \"(P::nat\<Rightarrow>bool) t\"}
   847   val assm2 = @{cprop \"(P::nat\<Rightarrow>bool) t\"}
   848 
   848 
   849   val Pt_implies_Qt = 
   849   val Pt_implies_Qt = 
   850         assume assm1
   850         assume assm1
   914 
   914 
   915 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
   915 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
   916 
   916 
   917 text {* 
   917 text {* 
   918   where the function @{ML "Thm.rule_attribute"} expects a function taking a 
   918   where the function @{ML "Thm.rule_attribute"} expects a function taking a 
   919   context (we ignore it in the code above) and a theorem (@{text thm}) and 
   919   context (which we ignore in the code above) and a theorem (@{text thm}), and 
   920   returns another theorem (namely @{text thm} resolved with the rule 
   920   returns another theorem (namely @{text thm} resolved with the lemma 
   921   @{thm sym[no_vars]}). The function @{ML "Thm.rule_attribute"} then returns 
   921   @{thm [source] sym}: @{thm sym[no_vars]}). The function @{ML "Thm.rule_attribute"} then returns 
   922   an attribute (of type @{ML_type "attribute"}).
   922   an attribute (of type @{ML_type "attribute"}).
   923 
   923 
   924   Before we can use the attribute, we need to set it up. This can be done
   924   Before we can use the attribute, we need to set it up. This can be done
   925   using the function @{ML Attrib.add_attributes} as follows.
   925   using the function @{ML Attrib.add_attributes} as follows.
   926 *}
   926 *}
   929   Attrib.add_attributes 
   929   Attrib.add_attributes 
   930     [("my_sym", Attrib.no_args my_symmetric, "applying the sym rule")]
   930     [("my_sym", Attrib.no_args my_symmetric, "applying the sym rule")]
   931 *}
   931 *}
   932 
   932 
   933 text {*
   933 text {*
   934   The attribute does not expect any further arguments (like @{text "[OF \<dots>]"} that 
   934   The attribute does not expect any further arguments (unlike @{text "[OF
   935   can take a list of theorems as argument). Therefore we use the function
   935   \<dots>]"}, for example, which can take a list of theorems as argument). Therefore
   936   @{ML Attrib.no_args}. Later on we will also consider attributes taking further
   936   we use the function @{ML Attrib.no_args}. Later on we will also consider
   937   arguments. An example for the attribute @{text "[my_sym]"} is the proof
   937   attributes taking further arguments. An example for the attribute @{text
       
   938   "[my_sym]"} is the proof
   938 *} 
   939 *} 
   939 
   940 
   940 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp
   941 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp
   941 
   942 
   942 text {*
   943 text {*