ProgTutorial/FirstSteps.thy
changeset 308 c90f4ec30d43
parent 307 f4fa6540e280
child 309 ed797395fab6
equal deleted inserted replaced
307:f4fa6540e280 308:c90f4ec30d43
   192 
   192 
   193 ML {* Toplevel.program (fn () => innocent ()) *}
   193 ML {* Toplevel.program (fn () => innocent ()) *}
   194 *)
   194 *)
   195 
   195 
   196 text {*
   196 text {*
   197   Most often you want to inspect data of type @{ML_type term}, @{ML_type cterm} 
   197   Most often you want to inspect data of Isabelle's most basic datastructures,
   198   or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing 
   198   namely @{ML_type term}, @{ML_type cterm} or @{ML_type thm}. Isabelle
   199   them (see Section \ref{sec:pretty}), 
   199   contains elaborate pretty-printing functions for printing them (see Section
   200   but  for quick-and-dirty solutions they are far too unwieldy. One way to transform 
   200   \ref{sec:pretty}), but for quick-and-dirty solutions they are far too
   201   a term into a string is to use the function @{ML [index] string_of_term in Syntax}.
   201   unwieldy. One way to transform a term into a string is to use the function
       
   202   @{ML [index] string_of_term in Syntax}.
       
   203 
   202 
   204 
   203   @{ML_response_fake [display,gray]
   205   @{ML_response_fake [display,gray]
   204   "Syntax.string_of_term @{context} @{term \"1::nat\"}"
   206   "Syntax.string_of_term @{context} @{term \"1::nat\"}"
   205   "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""}
   207   "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""}
   206 
   208 
   207   This produces a string with some additional information encoded in it. The string
   209   This produces a string with some additional information encoded in it. The string
   208   can be properly printed by using either the function @{ML [index] writeln} or 
   210   can be properly printed by using either the function @{ML [index] writeln} or 
   209   @{ML [index] tracing}.
   211   @{ML [index] tracing}:
   210 
   212 
   211   @{ML_response_fake [display,gray]
   213   @{ML_response_fake [display,gray]
   212   "writeln (Syntax.string_of_term @{context} @{term \"1::nat\"})"
   214   "writeln (Syntax.string_of_term @{context} @{term \"1::nat\"})"
   213   "\"1\""}
   215   "\"1\""}
   214 
   216 
       
   217   or
       
   218 
       
   219   @{ML_response_fake [display,gray]
       
   220   "tracing (Syntax.string_of_term @{context} @{term \"1::nat\"})"
       
   221   "\"1\""}
       
   222 
   215   A @{ML_type cterm} can be transformed into a string by the following function.
   223   A @{ML_type cterm} can be transformed into a string by the following function.
   216 *}
   224 *}
   217 
   225 
   218 ML{*fun string_of_cterm ctxt t =  
   226 ML{*fun string_of_cterm ctxt t =  
   219    Syntax.string_of_term ctxt (term_of t)*}
   227   Syntax.string_of_term ctxt (term_of t)*}
   220 
   228 
   221 text {*
   229 text {*
   222   In this example the function @{ML [index] term_of} extracts the @{ML_type term} from
   230   In this example the function @{ML [index] term_of} extracts the @{ML_type term} from
   223   a @{ML_type cterm}.  If there are more than one @{ML_type cterm}s to be
   231   a @{ML_type cterm}.  If there are more than one @{ML_type cterm}s to be
   224   printed, you can use the function @{ML [index] commas} to separate them.
   232   printed, you can use the function @{ML [index] commas} to separate them.
   225 *} 
   233 *} 
   226 
   234 
   227 ML{*fun string_of_cterms ctxt ts =  
   235 ML{*fun string_of_cterms ctxt ts =  
   228    commas (map (string_of_cterm ctxt) ts)*}
   236   commas (map (string_of_cterm ctxt) ts)*}
   229 
   237 
   230 text {*
   238 text {*
   231   The easiest way to get the string of a theorem is to transform it
   239   The easiest way to get the string of a theorem is to transform it
   232   into a @{ML_type cterm} using the function @{ML [index] crep_thm}. 
   240   into a @{ML_type cterm} using the function @{ML [index] crep_thm}. 
   233 *}
   241 *}
   243   "tracing (string_of_thm @{context} @{thm conjI})"
   251   "tracing (string_of_thm @{context} @{thm conjI})"
   244   "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"}
   252   "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"}
   245 
   253 
   246   In order to improve the readability of theorems we convert
   254   In order to improve the readability of theorems we convert
   247   these schematic variables into free variables using the 
   255   these schematic variables into free variables using the 
   248   function @{ML [index] import in Variable}.
   256   function @{ML [index] import in Variable}. This is similar
       
   257   to the attribute @{text "[no_vars]"} from Isabelle's user-level.
   249 *}
   258 *}
   250 
   259 
   251 ML{*fun no_vars ctxt thm =
   260 ML{*fun no_vars ctxt thm =
   252 let 
   261 let 
   253   val ((_, [thm']), _) = Variable.import true [thm] ctxt
   262   val ((_, [thm']), _) = Variable.import true [thm] ctxt
   493 *}
   502 *}
   494 
   503 
   495 ML{*fun (x, y) ||> f = (x, f y)*}
   504 ML{*fun (x, y) ||> f = (x, f y)*}
   496 
   505 
   497 text {*
   506 text {*
       
   507   These two functions can be used to avoid explicit @{text "lets"} for
       
   508   intermediate values in functions that return pairs. Suppose for example you
       
   509   want to separate a list of integers into two lists according to a
       
   510   treshold. For example if the treshold is @{ML "5"}, the list @{ML
       
   511   "[1,6,2,5,3,4]"} should be separated to @{ML "([1,2,3,4], [6,5])"}.  You
       
   512   can implement this function more concisely as
       
   513 *}
       
   514 
       
   515 ML{*fun separate i [] = ([], [])
       
   516   | separate i (x::xs) =
       
   517       let 
       
   518         val (los, grs) = separate i xs
       
   519       in
       
   520         if i <= x then (los, x::grs) else (x::los, grs)
       
   521       end*}
       
   522 
       
   523 text {*
       
   524   where however the return value of the recursive
       
   525   call is bound explicitly to the pair @{ML "(los, grs)" for los grs}. 
       
   526   This function can equally be written as
       
   527 *}
       
   528 
       
   529 ML{*fun separate i [] = ([], [])
       
   530   | separate i (x::xs) =
       
   531       if i <= x 
       
   532       then separate i xs ||> cons x
       
   533       else separate i xs |>> cons x*}
       
   534 
       
   535 text {*
       
   536   where no explicit @{text "let"} is needed. While in this example the gain is 
       
   537   only small, in more complicated situations the benefit of avoiding @{text "lets"} 
       
   538   can be substantial. 
       
   539 
   498   With the combinator @{ML [index] "|->"} you can re-combine the elements from a pair.
   540   With the combinator @{ML [index] "|->"} you can re-combine the elements from a pair.
   499   This combinator is defined as
   541   This combinator is defined as
   500 *}
   542 *}
   501 
   543 
   502 ML{*fun (x, y) |-> f = f x y*}
   544 ML{*fun (x, y) |-> f = f x y*}
   567   and @{ML_file "Pure/General/basics.ML"}. Also \isccite{sec:ML-linear-trans} 
   609   and @{ML_file "Pure/General/basics.ML"}. Also \isccite{sec:ML-linear-trans} 
   568   contains further information about combinators.
   610   contains further information about combinators.
   569   \end{readmore}
   611   \end{readmore}
   570  
   612  
   571   (FIXME: say something about calling conventions)
   613   (FIXME: say something about calling conventions)
       
   614  
       
   615   (FIXME: say something about singleton)
   572 *}
   616 *}
   573 
   617 
   574 
   618 
   575 section {* Antiquotations *}
   619 section {* Antiquotations *}
   576 
   620 
   683   It is also possible to define your own antiquotations. But you should
   727   It is also possible to define your own antiquotations. But you should
   684   exercise care when introducing new ones, as they can also make your
   728   exercise care when introducing new ones, as they can also make your
   685   code also difficult to read. In the next section we will see how the (build in) 
   729   code also difficult to read. In the next section we will see how the (build in) 
   686   antiquotation @{text "@{term \<dots>}"} can be used to construct terms.
   730   antiquotation @{text "@{term \<dots>}"} can be used to construct terms.
   687   A restriction of this antiquotation is that it does not allow you to
   731   A restriction of this antiquotation is that it does not allow you to
   688   use schematic variables. If you want an antiquotation that does not
   732   use schematic variables. If you want to have an antiquotation that does not
   689   have this restriction, you can implement your own using the 
   733   have this restriction, you can implement your own using the 
   690   function @{ML [index] ML_Antiquote.inline}. The code is as follows.
   734   function @{ML [index] ML_Antiquote.inline}. The code is as follows.
   691 *}
   735 *}
   692 
   736 
   693 ML %linenosgray{*ML_Antiquote.inline "term_pat"
   737 ML %linenosgray{*ML_Antiquote.inline "term_pat"
   696        s |> ProofContext.read_term_pattern ctxt
   740        s |> ProofContext.read_term_pattern ctxt
   697          |> ML_Syntax.print_term
   741          |> ML_Syntax.print_term
   698          |> ML_Syntax.atomic))*}
   742          |> ML_Syntax.atomic))*}
   699 
   743 
   700 text {*
   744 text {*
   701   We call the new antiquotation @{text "term_pat"} (Line 1); the parser in Line
   745   The parser in Line 2 provides us with a context and a string; this string is
   702   2 provides us with a context and a string; this string is transformed into a 
   746   transformed into a term using the function @{ML [index] read_term_pattern in
   703   term using the function @{ML [index] read_term_pattern in ProofContext} (Line 4);
   747   ProofContext} (Line 4); the next two lines print the term so that the
   704   the next two lines print the term so that the ML-system can understand 
   748   ML-system can understand them. An example of this antiquotation is as
   705   them. An example of this antiquotation is as follows.
   749   follows.
   706 
   750 
   707   @{ML_response_fake [display,gray]
   751   @{ML_response_fake [display,gray]
   708   "@{term_pat \"Suc (?x::nat)\"}"
   752   "@{term_pat \"Suc (?x::nat)\"}"
   709   "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"}
   753   "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"}
   710 
   754 
   772   abstractions for printing purposes, and so should be treated only as
   816   abstractions for printing purposes, and so should be treated only as
   773   ``comments''.  Application in Isabelle is realised with the term-constructor
   817   ``comments''.  Application in Isabelle is realised with the term-constructor
   774   @{ML $}.
   818   @{ML $}.
   775 
   819 
   776 
   820 
   777   Isabelle makes a distinction between \emph{free} variables (term-constructor @{ML Free})
   821   Isabelle makes a distinction between \emph{free} variables (term-constructor
   778   and variables (term-constructor @{ML Var}). The latter correspond to the schematic 
   822   @{ML Free} and written in blue colour) and \emph{schematic} variables
   779   variables that when printed show up with a question mark in front of them. Consider 
   823   (term-constructor @{ML Var} and written with a leading question mark). The
   780   the following two examples
   824   latter correspond to the schematic variables that when printed show up with
       
   825   a question mark in front of them. Consider the following two examples
       
   826 
   781   
   827   
   782   @{ML_response_fake [display, gray]
   828   @{ML_response_fake [display, gray]
   783 "let
   829 "let
   784   val v1 = Var ((\"x\", 3), @{typ bool})
   830   val v1 = Var ((\"x\", 3), @{typ bool})
   785   val v2 = Var ((\"x1\", 3), @{typ bool})
   831   val v2 = Var ((\"x1\", 3), @{typ bool})
   984   then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. 
  1030   then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. 
   985   This is a fundamental principle
  1031   This is a fundamental principle
   986   of Church-style typing, where variables with the same name still differ, if they 
  1032   of Church-style typing, where variables with the same name still differ, if they 
   987   have different type.
  1033   have different type.
   988 
  1034 
   989   There is also the function @{ML [index] subst_free} with which terms can 
  1035   There is also the function @{ML [index] subst_free} with which terms can be
   990   be replaced by other terms. For example below, we will replace in  
  1036   replaced by other terms. For example below, we will replace in @{term
   991   @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} 
  1037   "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by
   992   the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by @{term y}, and @{term x} by @{term True}.
  1038   @{term y}, and @{term x} by @{term True}.
   993 
  1039 
   994   @{ML_response_fake [display,gray]
  1040   @{ML_response_fake [display,gray]
   995 "let
  1041 "let
   996   val s1 = (@{term \"(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0\"}, @{term \"y::nat \<Rightarrow> nat\"})
  1042   val s1 = (@{term \"(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0\"}, @{term \"y::nat \<Rightarrow> nat\"})
   997   val s2 = (@{term \"x::nat\"}, @{term \"True\"})
  1043   val s2 = (@{term \"x::nat\"}, @{term \"True\"})
  1010   val trm = @{term \"(\<lambda>x::nat. x)\"}
  1056   val trm = @{term \"(\<lambda>x::nat. x)\"}
  1011 in
  1057 in
  1012   subst_free [s] trm
  1058   subst_free [s] trm
  1013 end"
  1059 end"
  1014   "Free (\"x\", \"nat\")"}
  1060   "Free (\"x\", \"nat\")"}
       
  1061 
       
  1062   Similarly the function @{ML [index] subst_bounds}, replaces lose bound 
       
  1063   variables with terms. To see how this function works, let us implement a
       
  1064   function that strips off the outermost quantifiers in a term.
       
  1065 *}
       
  1066 
       
  1067 ML {*
       
  1068 subst_bounds ([Free ("x", @{typ nat}), Free ("y", @{typ bool})], 
       
  1069   (Bound 1 $ Bound 0))
       
  1070 *}
       
  1071 
       
  1072 
       
  1073 ML{*fun strip_alls (Const ("All", _) $ Abs (n, T, t)) =
       
  1074     strip_alls t |>> cons (Free (n, T))
       
  1075   | strip_alls t = ([], t) *}
       
  1076 
       
  1077 text {*
       
  1078   The function returns a pair consisting of the stripped off variables and
       
  1079   the body of the universal quantifications. For example
       
  1080 
       
  1081   @{ML_response_fake [display, gray]
       
  1082   "strip_alls @{term \"\<forall>x y. x = (y::bool)\"}"
       
  1083 "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")],
       
  1084   Const (\"op =\", \<dots>) $ Bound 1 $ Bound 0)"}
       
  1085 
       
  1086   With the function @{ML subst_bounds}, you can replace the lose 
       
  1087   @{ML [index] Bound}s with the stripped off variables.
       
  1088 
       
  1089   @{ML_response_fake [display, gray, linenos]
       
  1090   "let
       
  1091   val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"}
       
  1092 in 
       
  1093   subst_bounds (rev vrs, trm) 
       
  1094   |> Syntax.string_of_term @{context}
       
  1095   |> tracing
       
  1096 end"
       
  1097   "x = y"}
       
  1098 
       
  1099   Note that in Line 4 we had to reverse the list of variables that @{ML strip_alls}
       
  1100   returned. The reason is that the head of the list the function @{ML subst_bounds}
       
  1101   takes is the replacement for @{ML "Bound 0"}, the next element for @{ML "Bound 1"}
       
  1102   and so on. 
  1015 
  1103 
  1016   There are many convenient functions that construct specific HOL-terms. For
  1104   There are many convenient functions that construct specific HOL-terms. For
  1017   example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms.
  1105   example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms.
  1018   The types needed in this equality are calculated from the type of the
  1106   The types needed in this equality are calculated from the type of the
  1019   arguments. For example
  1107   arguments. For example