CookBook/FirstSteps.thy
changeset 122 79696161ae16
parent 120 c39f83d8daeb
child 123 460bc2ee14e9
equal deleted inserted replaced
121:26e5b41faa74 122:79696161ae16
   112   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   112   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   113   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   113   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   114 
   114 
   115   You can print out error messages with the function @{ML error}; for example:
   115   You can print out error messages with the function @{ML error}; for example:
   116 
   116 
   117   @{ML_response_fake [display,gray] "if 0=1 then 1 else (error \"foo\")" "\"foo\""}
   117 @{ML_response_fake [display,gray] "if 0=1 then true else (error \"foo\")" 
       
   118 "Exception- ERROR \"foo\" raised
       
   119 At command \"ML\"."}
   118 
   120 
   119   Section~\ref{sec:printing} will give more information about printing 
   121   Section~\ref{sec:printing} will give more information about printing 
   120   the main data structures of Isabelle, namely @{ML_type term}, @{ML_type cterm} 
   122   the main data structures of Isabelle, namely @{ML_type term}, @{ML_type cterm} 
   121   and @{ML_type thm}.
   123   and @{ML_type thm}.
   122 *}
   124 *}
   123 
       
   124 
       
   125 
   125 
   126 
   126 
   127 section {* Antiquotations *}
   127 section {* Antiquotations *}
   128 
   128 
   129 text {*
   129 text {*
   159 
   159 
   160   In a similar way you can use antiquotations to refer to proved theorems:
   160   In a similar way you can use antiquotations to refer to proved theorems:
   161 
   161 
   162   @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"}
   162   @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"}
   163 
   163 
   164   and simpsets:
   164   and current simpsets:
   165 
   165 
   166   @{ML_response_fake [display,gray] 
   166   @{ML_response_fake [display,gray] 
   167 "let
   167 "let
   168   val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset}
   168   val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset}
   169 in
   169 in
   170   map #name (Net.entries rules)
   170   map #name (Net.entries rules)
   171 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   171 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"}
   172 
   172 
   173   The code about simpsets extracts the theorem names stored in the
   173   The code about simpsets extracts the theorem names stored in the
   174   current simpset.  You can get hold of the current simpset with the antiquotation 
   174   simpset.  You can get hold of the current simpset with the antiquotation 
   175   @{text "@{simpset}"}.  The function @{ML rep_ss in MetaSimplifier} returns a record
   175   @{text "@{simpset}"}.  The function @{ML rep_ss in MetaSimplifier} returns a record
   176   containing all information about the simpset. The rules of a simpset are
   176   containing all information about the simpset. The rules of a simpset are
   177   stored in a \emph{discrimination net} (a data structure for fast
   177   stored in a \emph{discrimination net} (a data structure for fast
   178   indexing). From this net you can extract the entries using the function @{ML
   178   indexing). From this net you can extract the entries using the function @{ML
   179   Net.entries}.
   179   Net.entries}.
   195   These bindings are difficult to maintain and also can be accidentally
   195   These bindings are difficult to maintain and also can be accidentally
   196   overwritten by the user. This often breakes Isabelle
   196   overwritten by the user. This often breakes Isabelle
   197   packages. Antiquotations solve this problem, since they are ``linked''
   197   packages. Antiquotations solve this problem, since they are ``linked''
   198   statically at compile-time.  However, this static linkage also limits their
   198   statically at compile-time.  However, this static linkage also limits their
   199   usefulness in cases where data needs to be build up dynamically. In the
   199   usefulness in cases where data needs to be build up dynamically. In the
   200   course of this introduction, we will learn more about these antiquotations:
   200   course of this introduction, you will learn more about these antiquotations:
   201   they greatly simplify Isabelle programming since one can directly access all
   201   they can simplify Isabelle programming since one can directly access all
   202   kinds of logical elements from th ML-level.
   202   kinds of logical elements from th ML-level.
   203 
   203 
   204 *}
   204 *}
   205 
   205 
   206 section {* Terms and Types *}
   206 section {* Terms and Types *}
   207 
   207 
   208 text {*
   208 text {*
   209   One way to construct terms of Isabelle on the ML-level is by using the antiquotation 
   209   One way to construct terms of Isabelle is by using the antiquotation 
   210   \mbox{@{text "@{term \<dots>}"}}. For example:
   210   \mbox{@{text "@{term \<dots>}"}}. For example:
   211 
   211 
   212   @{ML_response [display,gray] 
   212   @{ML_response [display,gray] 
   213 "@{term \"(a::nat) + b = c\"}" 
   213 "@{term \"(a::nat) + b = c\"}" 
   214 "Const (\"op =\", \<dots>) $ 
   214 "Const (\"op =\", \<dots>) $ 
   243   \item @{term "{ [x::int] | x. x \<le> -2 }"}  
   243   \item @{term "{ [x::int] | x. x \<le> -2 }"}  
   244   \end{itemize}
   244   \end{itemize}
   245 
   245 
   246   Hint: The third term is already quite big, and the pretty printer
   246   Hint: The third term is already quite big, and the pretty printer
   247   may omit parts of it by default. If you want to see all of it, you
   247   may omit parts of it by default. If you want to see all of it, you
   248   can use the following ML-function to set the limit to a value high 
   248   can use the following ML-function to set the printing depth to a higher 
   249   enough:
   249   value:
   250 
   250 
   251   @{ML [display,gray] "print_depth 50"}
   251   @{ML [display,gray] "print_depth 50"}
   252   \end{exercise}
   252   \end{exercise}
   253 
   253 
   254   The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, 
   254   The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, 
   321     "Const \<dots> $ 
   321     "Const \<dots> $ 
   322     Abs (\"x\", \<dots>,
   322     Abs (\"x\", \<dots>,
   323       Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   323       Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   324                   (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   324                   (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   325 
   325 
   326   (FIXME: expand the following point)
       
   327 
       
   328   One tricky point in constructing terms by hand is to obtain the fully
       
   329   qualified name for constants. For example the names for @{text "zero"} and
       
   330   @{text "+"} are more complex than one first expects, namely
       
   331 
       
   332 
       
   333   \begin{center}
       
   334   @{text "HOL.zero_class.zero"} and @{text "HOL.plus_class.plus"}. 
       
   335   \end{center}
       
   336   
       
   337   The extra prefixes @{text zero_class} and @{text plus_class} are present
       
   338   because these constants are defined within type classes; the prefix @{text
       
   339   "HOL"} indicates in which theory they are defined. Guessing such internal
       
   340   names can sometimes be quite hard. Therefore Isabelle provides the
       
   341   antiquotation @{text "@{const_name \<dots>}"} which does the expansion
       
   342   automatically, for example:
       
   343 
       
   344   @{ML_response_fake [display,gray] "@{const_name \"Nil\"}" "List.list.Nil"}
       
   345 
       
   346   (FIXME: Is it useful to explain @{text "@{const_syntax}"}?)
       
   347 
       
   348   Although types of terms can often be inferred, there are many
   326   Although types of terms can often be inferred, there are many
   349   situations where you need to construct types manually, especially  
   327   situations where you need to construct types manually, especially  
   350   when defining constants. For example the function returning a function 
   328   when defining constants. For example the function returning a function 
   351   type is as follows:
   329   type is as follows:
   352 
   330 
   357 text {* This can be equally written as: *}
   335 text {* This can be equally written as: *}
   358 
   336 
   359 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
   337 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *}
   360 
   338 
   361 text {*
   339 text {*
   362 
       
   363   \begin{readmore}
   340   \begin{readmore}
   364   There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and
   341   There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and
   365   @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms 
   342   @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms 
   366   and types easier.\end{readmore}
   343   and types easier.\end{readmore}
   367 
   344 
   368   Have a look at these files and try to solve the following two exercises:
   345   Have a look at these files and try to solve the following two exercises:
   369 
       
   370 *}
   346 *}
   371 
   347 
   372 text {*
   348 text {*
   373 
   349 
   374   \begin{exercise}\label{fun:revsum}
   350   \begin{exercise}\label{fun:revsum}
   375   Write a function @{text "rev_sum : term -> term"} that takes a
   351   Write a function @{text "rev_sum : term -> term"} that takes a
   376   term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "i"} might be zero)
   352   term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "n"} might be zero)
   377   and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume
   353   and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume
   378   the @{text "t\<^isub>i"} can be arbitrary expressions and also note that @{text "+"} 
   354   the @{text "t\<^isub>i"} can be arbitrary expressions and also note that @{text "+"} 
   379   associates to the left. Try your function on some examples. 
   355   associates to the left. Try your function on some examples. 
   380   \end{exercise}
   356   \end{exercise}
   381 
   357 
   385   number representing their sum.
   361   number representing their sum.
   386   \end{exercise}
   362   \end{exercise}
   387 
   363 
   388   A handy function for manipulating terms is @{ML map_types}: it takes a 
   364   A handy function for manipulating terms is @{ML map_types}: it takes a 
   389   function and applies it to every type in the term. You can, for example,
   365   function and applies it to every type in the term. You can, for example,
   390   change every @{typ nat} in a term into an @{typ int} using the function
   366   change every @{typ nat} in a term into an @{typ int} using the function:
   391 *}
   367 *}
   392 
   368 
   393 ML{*fun nat_to_int t =
   369 ML{*fun nat_to_int t =
   394   (case t of
   370   (case t of
   395      @{typ nat} => @{typ int}
   371      @{typ nat} => @{typ int}
   396    | Type (s, ts) => Type (s, map nat_to_int ts)
   372    | Type (s, ts) => Type (s, map nat_to_int ts)
   397    | _ => t)*}
   373    | _ => t)*}
   398 
   374 
   399 text {*
   375 text {*
   400   an then apply it as follows:
   376   An example as follows:
   401 
       
   402 
   377 
   403 @{ML_response_fake [display,gray] 
   378 @{ML_response_fake [display,gray] 
   404 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
   379 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
   405 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
   380 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
   406            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
   381            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
   454 
   429 
   455   (FIXME: @{text "ctyp_of"}, @{ML fastype_of}, @{text dummyT})
   430   (FIXME: @{text "ctyp_of"}, @{ML fastype_of}, @{text dummyT})
   456 
   431 
   457 *}
   432 *}
   458 
   433 
       
   434 section {* Constants *}
       
   435 
       
   436 text {*
       
   437   There are a few subtle issues with constants. They usually crop up when
       
   438   pattern matching terms or constructing term. While it is perfectly ok
       
   439   to write the function @{text is_true} as follows
       
   440 *}
       
   441 
       
   442 ML{*fun is_true @{term True} = true
       
   443   | is_true _ = false*}
       
   444 
       
   445 text {*
       
   446   this does not work for picking out @{text "\<forall>"}-quantified terms. Because
       
   447   the function 
       
   448 *}
       
   449 
       
   450 ML{*fun is_all (@{term All} $ _) = true
       
   451   | is_all _ = false*}
       
   452 
       
   453 text {* 
       
   454   will not correctly match: 
       
   455 
       
   456   @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "false"}
       
   457 
       
   458   The problem is that the @{text "@term"}-antiquotation in the pattern 
       
   459   fixes the type of @{term "All"} to be @{typ "('a \<Rightarrow> bool) \<Rightarrow> bool"} for 
       
   460   an arbitrary, but fixed type @{typ "'a"}. A properly working alternative 
       
   461   for this function is
       
   462 *}
       
   463 
       
   464 ML{*fun is_all (Const ("All", _) $ _) = true
       
   465   | is_all _ = false*}
       
   466 
       
   467 text {* 
       
   468   because now
       
   469 
       
   470 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"}
       
   471 
       
   472   matches correctly.
       
   473 
       
   474   However there is still a problem: consider the function that attempts to 
       
   475   pick out a @{text "Nil"}-term:
       
   476 *}
       
   477 
       
   478 ML{*fun is_nil (Const ("Nil", _)) = true
       
   479   | is_nil _ = false *}
       
   480 
       
   481 text {* 
       
   482   Unfortunately, also this one does not return the expected result, since
       
   483 
       
   484   @{ML_response [display,gray] "is_nil @{term \"Nil\"}" "false"}
       
   485 
       
   486   The problem is that on the ML-level the name of constants is not
       
   487   immediately clear. If you look at
       
   488 
       
   489   @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"}
       
   490 
       
   491   the name of the constant depends on the theory in which the term constructor
       
   492   @{text "Nil"} is defined and also in which datatype. Even worse, some
       
   493   constants have an even more complex name involving type-classes. Consider 
       
   494   for example
       
   495 
       
   496   @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" 
       
   497   "(Const (\"HOL.zero_class.zero\", \<dots>), 
       
   498  Const (\"HOL.times_class.times\", \<dots>))"}
       
   499 
       
   500   While you could always use the complete name, for example 
       
   501   @{ML "Const (\"List.list.Nil\", @{typ \"nat list\"})"}, for referring to or
       
   502   matching against @{text "Nil"}, this would make the code rather brittle. 
       
   503   The reason is that the theory and the name of the datatype can easily change. 
       
   504   To make the code more robust it is better to use the antiquotation 
       
   505   @{text "@{const_name \<dots>}"}. With this antiquotation you can harness the 
       
   506   variable parts of the constant's name. Therefore the functions for 
       
   507   matching against constants should be written as follows.
       
   508 *}
       
   509 
       
   510 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true
       
   511   | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true
       
   512   | is_nil_or_all _ = false *}
       
   513 
       
   514 text {*
       
   515   Having said this, you also frequently have to calculate what the
       
   516   ``base''  name of a constant is. For this you can use the function 
       
   517   @{ML Sign.base_name}. For example:
       
   518   
       
   519   (FIXME is there an example for that statement?)
       
   520 
       
   521 
       
   522   @{ML_response [display,gray] "Sign.base_name \"List.list.Nil\"" "\"Nil\""}
       
   523 
       
   524   (FIXME authentic syntax?)
       
   525 
       
   526   \begin{readmore}
       
   527   FIXME
       
   528   \end{readmore}
       
   529 *}
       
   530 
       
   531 
   459 section {* Theorems *}
   532 section {* Theorems *}
   460 
   533 
   461 text {*
   534 text {*
   462   Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} 
   535   Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} 
   463   that can only be built by going through interfaces. As a consequence, every proof 
   536   that can only be build by going through interfaces. As a consequence, every proof 
   464   in Isabelle is correct by construction. 
   537   in Isabelle is correct by construction. 
   465 
   538 
   466   (FIXME reference LCF-philosophy)
   539   (FIXME reference LCF-philosophy)
   467 
   540 
   468   To see theorems in ``action'', let us give a proof on the ML-level for the following 
   541   To see theorems in ``action'', let us give a proof on the ML-level for the following 
   583 
   656 
   584 ML{*fun str_of_thms ctxt thms =  
   657 ML{*fun str_of_thms ctxt thms =  
   585   commas (map (str_of_thm ctxt) thms)*}
   658   commas (map (str_of_thm ctxt) thms)*}
   586 
   659 
   587 
   660 
   588 section {* Operations on Constants (Names) *}
       
   589 
       
   590 text {*
       
   591 
       
   592 @{ML_response [display] "Sign.base_name \"List.list.Nil\"" "\"Nil\""}
       
   593 
       
   594   authentic syntax?
       
   595 
       
   596 *}
       
   597 
       
   598 ML {* @{const_name lfp} *}
       
   599 
       
   600 text {*
       
   601   constants in case-patterns?
       
   602 
       
   603   In the meantime, lfp has been moved to the Inductive theory, so it is  
       
   604   no longer called Lfp.lfp. If a @{text "@{const_name}"} antiquotation had been  
       
   605   used, we would have gotten an error for this. Another advantage of the  
       
   606   antiquotation is that we can then just write @{text "@{const_name lfp}"} rather  
       
   607   than @{text "@{const_name Lfp.lfp}"} or whatever, and it expands to the correct  
       
   608   name.
       
   609   
       
   610 *}
       
   611 
       
   612 section {* Combinators\label{sec:combinators} *}
   661 section {* Combinators\label{sec:combinators} *}
   613 
   662 
   614 text {*
   663 text {*
   615   For beginners, perhaps the most puzzling parts in the existing code of Isabelle are
   664   For beginners, perhaps the most puzzling parts in the existing code of Isabelle are
   616   the combinators. At first they seem to greatly obstruct the
   665   the combinators. At first they seem to greatly obstruct the