ProgTutorial/FirstSteps.thy
changeset 256 1fb8d62c88a0
parent 255 ef1da1abee46
child 257 ce0f60d0351e
equal deleted inserted replaced
255:ef1da1abee46 256:1fb8d62c88a0
   109 
   109 
   110 text {*
   110 text {*
   111 
   111 
   112   During development you might find it necessary to inspect some data
   112   During development you might find it necessary to inspect some data
   113   in your code. This can be done in a ``quick-and-dirty'' fashion using 
   113   in your code. This can be done in a ``quick-and-dirty'' fashion using 
   114   the function @{ML [indexc] "writeln"}. For example 
   114   the function @{ML [index] "writeln"}. For example 
   115 
   115 
   116   @{ML_response_fake [display,gray] "writeln \"any string\"" "\"any string\""}
   116   @{ML_response_fake [display,gray] "writeln \"any string\"" "\"any string\""}
   117 
   117 
   118   will print out @{text [quotes] "any string"} inside the response buffer
   118   will print out @{text [quotes] "any string"} inside the response buffer
   119   of Isabelle.  This function expects a string as argument. If you develop under PolyML,
   119   of Isabelle.  This function expects a string as argument. If you develop under PolyML,
   120   then there is a convenient, though again ``quick-and-dirty'', method for
   120   then there is a convenient, though again ``quick-and-dirty'', method for
   121   converting values into strings, namely the function @{ML PolyML.makestring}:
   121   converting values into strings, namely the function @{ML PolyML.makestring}:
   122 
   122 
   123   @{ML_response_fake [display,gray] "writeln (PolyML.makestring 1)" "\"1\""} 
   123   @{ML_response_fake [display,gray] "writeln (PolyML.makestring 1)" "\"1\""} 
   124 
   124 
   125   However, @{ML makestring} only works if the type of what is converted is monomorphic 
   125   However, @{ML [index] makestring} only works if the type of what is converted is monomorphic 
   126   and not a function.
   126   and not a function.
   127 
   127 
   128   The function @{ML "writeln"} should only be used for testing purposes, because any
   128   The function @{ML "writeln"} should only be used for testing purposes, because any
   129   output this function generates will be overwritten as soon as an error is
   129   output this function generates will be overwritten as soon as an error is
   130   raised. For printing anything more serious and elaborate, the
   130   raised. For printing anything more serious and elaborate, the
   131   function @{ML tracing} is more appropriate. This function writes all output into
   131   function @{ML [index] tracing} is more appropriate. This function writes all output into
   132   a separate tracing buffer. For example:
   132   a separate tracing buffer. For example:
   133 
   133 
   134   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
   134   @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""}
   135 
   135 
   136   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
   136   It is also possible to redirect the ``channel'' where the string @{text "foo"} is 
   153 
   153 
   154 text {*
   154 text {*
   155   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   155   Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} 
   156   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   156   will cause that all tracing information is printed into the file @{text "foo.bar"}.
   157 
   157 
   158   You can print out error messages with the function @{ML error}; for example:
   158   You can print out error messages with the function @{ML [index] error}; for example:
   159 
   159 
   160 @{ML_response_fake [display,gray] "if 0=1 then true else (error \"foo\")" 
   160 @{ML_response_fake [display,gray] "if 0=1 then true else (error \"foo\")" 
   161 "Exception- ERROR \"foo\" raised
   161 "Exception- ERROR \"foo\" raised
   162 At command \"ML\"."}
   162 At command \"ML\"."}
   163 
   163 
   164   (FIXME Mention how to work with @{ML Toplevel.debug} and @{ML Toplevel.profiling}.)
   164   (FIXME Mention how to work with @{ML [index] debug in Toplevel} and 
       
   165   @{ML [index] profiling in Toplevel}.)
   165 *}
   166 *}
   166 
   167 
   167 (*
   168 (*
   168 ML {* reset Toplevel.debug *}
   169 ML {* reset Toplevel.debug *}
   169 
   170 
   181 text {*
   182 text {*
   182   Most often you want to inspect data of type @{ML_type term}, @{ML_type cterm} 
   183   Most often you want to inspect data of type @{ML_type term}, @{ML_type cterm} 
   183   or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing 
   184   or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing 
   184   them (see Section \ref{sec:pretty}), 
   185   them (see Section \ref{sec:pretty}), 
   185   but  for quick-and-dirty solutions they are far too unwieldy. A simple way to transform 
   186   but  for quick-and-dirty solutions they are far too unwieldy. A simple way to transform 
   186   a term into a string is to use the function @{ML Syntax.string_of_term}.
   187   a term into a string is to use the function @{ML [index] string_of_term in Syntax}.
   187 
   188 
   188   @{ML_response_fake [display,gray]
   189   @{ML_response_fake [display,gray]
   189   "Syntax.string_of_term @{context} @{term \"1::nat\"}"
   190   "Syntax.string_of_term @{context} @{term \"1::nat\"}"
   190   "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""}
   191   "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""}
   191 
   192 
   192   This produces a string with some additional information encoded in it. The string
   193   This produces a string with some additional information encoded in it. The string
   193   can be properly printed by using the function @{ML writeln}.
   194   can be properly printed by using the function @{ML [index] writeln}.
   194 
   195 
   195   @{ML_response_fake [display,gray]
   196   @{ML_response_fake [display,gray]
   196   "writeln (Syntax.string_of_term @{context} @{term \"1::nat\"})"
   197   "writeln (Syntax.string_of_term @{context} @{term \"1::nat\"})"
   197   "\"1\""}
   198   "\"1\""}
   198 
   199 
   201 
   202 
   202 ML{*fun string_of_cterm ctxt t =  
   203 ML{*fun string_of_cterm ctxt t =  
   203    Syntax.string_of_term ctxt (term_of t)*}
   204    Syntax.string_of_term ctxt (term_of t)*}
   204 
   205 
   205 text {*
   206 text {*
   206   In this example the function @{ML term_of} extracts the @{ML_type term} from
   207   In this example the function @{ML [index] term_of} extracts the @{ML_type term} from
   207   a @{ML_type cterm}.  If there are more than one @{ML_type cterm}s to be
   208   a @{ML_type cterm}.  If there are more than one @{ML_type cterm}s to be
   208   printed, you can use the function @{ML commas} to separate them.
   209   printed, you can use the function @{ML [index] commas} to separate them.
   209 *} 
   210 *} 
   210 
   211 
   211 ML{*fun string_of_cterms ctxt ts =  
   212 ML{*fun string_of_cterms ctxt ts =  
   212    commas (map (string_of_cterm ctxt) ts)*}
   213    commas (map (string_of_cterm ctxt) ts)*}
   213 
   214 
   214 text {*
   215 text {*
   215   The easiest way to get the string of a theorem is to transform it
   216   The easiest way to get the string of a theorem is to transform it
   216   into a @{ML_type cterm} using the function @{ML crep_thm}. 
   217   into a @{ML_type cterm} using the function @{ML [index] crep_thm}. 
   217 *}
   218 *}
   218 
   219 
   219 ML{*fun string_of_thm ctxt thm =
   220 ML{*fun string_of_thm ctxt thm =
   220   string_of_cterm ctxt (#prop (crep_thm thm))*}
   221   string_of_cterm ctxt (#prop (crep_thm thm))*}
   221 
   222 
   227   "writeln (string_of_thm @{context} @{thm conjI})"
   228   "writeln (string_of_thm @{context} @{thm conjI})"
   228   "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"}
   229   "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"}
   229 
   230 
   230   In order to improve the readability of theorems we convert
   231   In order to improve the readability of theorems we convert
   231   these schematic variables into free variables using the 
   232   these schematic variables into free variables using the 
   232   function @{ML Variable.import_thms}.
   233   function @{ML [index] import_thms in Variable}.
   233 *}
   234 *}
   234 
   235 
   235 ML{*fun no_vars ctxt thm =
   236 ML{*fun no_vars ctxt thm =
   236 let 
   237 let 
   237   val ((_, [thm']), _) = Variable.import_thms true [thm] ctxt
   238   val ((_, [thm']), _) = Variable.import_thms true [thm] ctxt
   264   For beginners perhaps the most puzzling parts in the existing code of Isabelle are
   265   For beginners perhaps the most puzzling parts in the existing code of Isabelle are
   265   the combinators. At first they seem to greatly obstruct the
   266   the combinators. At first they seem to greatly obstruct the
   266   comprehension of the code, but after getting familiar with them, they
   267   comprehension of the code, but after getting familiar with them, they
   267   actually ease the understanding and also the programming.
   268   actually ease the understanding and also the programming.
   268 
   269 
   269   The simplest combinator is @{ML I}, which is just the identity function defined as
   270   The simplest combinator is @{ML [index] I}, which is just the identity function defined as
   270 *}
   271 *}
   271 
   272 
   272 ML{*fun I x = x*}
   273 ML{*fun I x = x*}
   273 
   274 
   274 text {* Another simple combinator is @{ML K}, defined as *}
   275 text {* Another simple combinator is @{ML [index] K}, defined as *}
   275 
   276 
   276 ML{*fun K x = fn _ => x*}
   277 ML{*fun K x = fn _ => x*}
   277 
   278 
   278 text {*
   279 text {*
   279   @{ML K} ``wraps'' a function around the argument @{text "x"}. However, this 
   280   @{ML [index] K} ``wraps'' a function around the argument @{text "x"}. However, this 
   280   function ignores its argument. As a result, @{ML K} defines a constant function 
   281   function ignores its argument. As a result, @{ML K} defines a constant function 
   281   always returning @{text x}.
   282   always returning @{text x}.
   282 
   283 
   283   The next combinator is reverse application, @{ML "|>"}, defined as: 
   284   The next combinator is reverse application, @{ML [index] "|>"}, defined as: 
   284 *}
   285 *}
   285 
   286 
   286 ML{*fun x |> f = f x*}
   287 ML{*fun x |> f = f x*}
   287 
   288 
   288 text {* While just syntactic sugar for the usual function application,
   289 text {* While just syntactic sugar for the usual function application,
   350  |> Syntax.string_of_term @{context}
   351  |> Syntax.string_of_term @{context}
   351  |> writeln"
   352  |> writeln"
   352   "P z za zb"}
   353   "P z za zb"}
   353 
   354 
   354   You can read off this behaviour from how @{ML apply_fresh_args} is
   355   You can read off this behaviour from how @{ML apply_fresh_args} is
   355   coded: in Line 2, the function @{ML fastype_of} calculates the type of the
   356   coded: in Line 2, the function @{ML [index] fastype_of} calculates the type of the
   356   function; @{ML binder_types} in the next line produces the list of argument
   357   function; @{ML [index] binder_types} in the next line produces the list of argument
   357   types (in the case above the list @{text "[nat, int, unit]"}); Line 4 
   358   types (in the case above the list @{text "[nat, int, unit]"}); Line 4 
   358   pairs up each type with the string  @{text "z"}; the
   359   pairs up each type with the string  @{text "z"}; the
   359   function @{ML variant_frees in Variable} generates for each @{text "z"} a
   360   function @{ML [index] variant_frees in Variable} generates for each @{text "z"} a
   360   unique name avoiding the given @{text f}; the list of name-type pairs is turned
   361   unique name avoiding the given @{text f}; the list of name-type pairs is turned
   361   into a list of variable terms in Line 6, which in the last line is applied
   362   into a list of variable terms in Line 6, which in the last line is applied
   362   by the function @{ML list_comb} to the function. In this last step we have to 
   363   by the function @{ML [index] list_comb} to the function. In this last step we have to 
   363   use the function @{ML curry}, because @{ML list_comb} expects the function and the
   364   use the function @{ML [index] curry}, because @{ML [index] list_comb} expects the 
   364   variables list as a pair. This kind of functions is often needed when
   365   function and the variables list as a pair. This kind of functions is often needed when
   365   constructing terms and the infrastructure helps tremendously to avoid
   366   constructing terms and the infrastructure helps tremendously to avoid
   366   any name clashes. Consider for example: 
   367   any name clashes. Consider for example: 
   367 
   368 
   368    @{ML_response_fake [display,gray]
   369    @{ML_response_fake [display,gray]
   369 "apply_fresh_args @{term \"za::'a \<Rightarrow> 'b \<Rightarrow> 'c\"} @{context} 
   370 "apply_fresh_args @{term \"za::'a \<Rightarrow> 'b \<Rightarrow> 'c\"} @{context} 
   370  |> Syntax.string_of_term @{context}
   371  |> Syntax.string_of_term @{context}
   371  |> writeln"
   372  |> writeln"
   372   "za z zb"}
   373   "za z zb"}
   373   
   374   
   374   The combinator @{ML "#>"} is the reverse function composition. It can be
   375   The combinator @{ML [index] "#>"} is the reverse function composition. It can be
   375   used to define the following function
   376   used to define the following function
   376 *}
   377 *}
   377 
   378 
   378 ML{*val inc_by_six = 
   379 ML{*val inc_by_six = 
   379       (fn x => x + 1)
   380       (fn x => x + 1)
   384   which is the function composed of first the increment-by-one function and then
   385   which is the function composed of first the increment-by-one function and then
   385   increment-by-two, followed by increment-by-three. Again, the reverse function 
   386   increment-by-two, followed by increment-by-three. Again, the reverse function 
   386   composition allows you to read the code top-down.
   387   composition allows you to read the code top-down.
   387 
   388 
   388   The remaining combinators described in this section add convenience for the
   389   The remaining combinators described in this section add convenience for the
   389   ``waterfall method'' of writing functions. The combinator @{ML tap} allows
   390   ``waterfall method'' of writing functions. The combinator @{ML [index] tap} allows
   390   you to get hold of an intermediate result (to do some side-calculations for
   391   you to get hold of an intermediate result (to do some side-calculations for
   391   instance). The function
   392   instance). The function
   392 
   393 
   393  *}
   394  *}
   394 
   395 
   397        |> tap (fn x => tracing (PolyML.makestring x))
   398        |> tap (fn x => tracing (PolyML.makestring x))
   398        |> (fn x => x + 2)*}
   399        |> (fn x => x + 2)*}
   399 
   400 
   400 text {* 
   401 text {* 
   401   increments the argument first by @{text "1"} and then by @{text "2"}. In the
   402   increments the argument first by @{text "1"} and then by @{text "2"}. In the
   402   middle (Line 3), however, it uses @{ML tap} for printing the ``plus-one''
   403   middle (Line 3), however, it uses @{ML [index] tap} for printing the ``plus-one''
   403   intermediate result inside the tracing buffer. The function @{ML tap} can
   404   intermediate result inside the tracing buffer. The function @{ML [index] tap} can
   404   only be used for side-calculations, because any value that is computed
   405   only be used for side-calculations, because any value that is computed
   405   cannot be merged back into the ``main waterfall''. To do this, you can use
   406   cannot be merged back into the ``main waterfall''. To do this, you can use
   406   the next combinator.
   407   the next combinator.
   407 
   408 
   408   The combinator @{ML "`"} (a backtick) is similar to @{ML tap}, but applies a
   409   The combinator @{ML [index] "`"} (a backtick) is similar to @{ML tap}, but applies a
   409   function to the value and returns the result together with the value (as a
   410   function to the value and returns the result together with the value (as a
   410   pair). For example the function 
   411   pair). For example the function 
   411 *}
   412 *}
   412 
   413 
   413 ML{*fun inc_as_pair x =
   414 ML{*fun inc_as_pair x =
   418   takes @{text x} as argument, and then increments @{text x}, but also keeps
   419   takes @{text x} as argument, and then increments @{text x}, but also keeps
   419   @{text x}. The intermediate result is therefore the pair @{ML "(x + 1, x)"
   420   @{text x}. The intermediate result is therefore the pair @{ML "(x + 1, x)"
   420   for x}. After that, the function increments the right-hand component of the
   421   for x}. After that, the function increments the right-hand component of the
   421   pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}.
   422   pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}.
   422 
   423 
   423   The combinators @{ML "|>>"} and @{ML "||>"} are defined for 
   424   The combinators @{ML [index] "|>>"} and @{ML [index] "||>"} are defined for 
   424   functions manipulating pairs. The first applies the function to
   425   functions manipulating pairs. The first applies the function to
   425   the first component of the pair, defined as
   426   the first component of the pair, defined as
   426 *}
   427 *}
   427 
   428 
   428 ML{*fun (x, y) |>> f = (f x, y)*}
   429 ML{*fun (x, y) |>> f = (f x, y)*}
   432 *}
   433 *}
   433 
   434 
   434 ML{*fun (x, y) ||> f = (x, f y)*}
   435 ML{*fun (x, y) ||> f = (x, f y)*}
   435 
   436 
   436 text {*
   437 text {*
   437   With the combinator @{ML "|->"} you can re-combine the elements from a pair.
   438   With the combinator @{ML [index] "|->"} you can re-combine the elements from a pair.
   438   This combinator is defined as
   439   This combinator is defined as
   439 *}
   440 *}
   440 
   441 
   441 ML{*fun (x, y) |-> f = f x y*}
   442 ML{*fun (x, y) |-> f = f x y*}
   442 
   443 
   448 ML{*fun double x =
   449 ML{*fun double x =
   449       x |>  (fn x => (x, x))
   450       x |>  (fn x => (x, x))
   450         |-> (fn x => fn y => x + y)*}
   451         |-> (fn x => fn y => x + y)*}
   451 
   452 
   452 text {* 
   453 text {* 
   453   The combinator @{ML ||>>} plays a central rôle whenever your task is to update a 
   454   The combinator @{ML [index] ||>>} plays a central rôle whenever your task is to update a 
   454   theory and the update also produces a side-result (for example a theorem). Functions 
   455   theory and the update also produces a side-result (for example a theorem). Functions 
   455   for such tasks return a pair whose second component is the theory and the fist 
   456   for such tasks return a pair whose second component is the theory and the fist 
   456   component is the side-result. Using @{ML ||>>}, you can do conveniently the update 
   457   component is the side-result. Using @{ML [index] ||>>}, you can do conveniently the update 
   457   and also accumulate the side-results. Considder the following simple function. 
   458   and also accumulate the side-results. Considder the following simple function. 
   458 *}
   459 *}
   459 
   460 
   460 ML %linenosgray{*fun acc_incs x =
   461 ML %linenosgray{*fun acc_incs x =
   461     x |> (fn x => ("", x)) 
   462     x |> (fn x => ("", x)) 
   463       ||>> (fn x => (x, x + 1))
   464       ||>> (fn x => (x, x + 1))
   464       ||>> (fn x => (x, x + 1))*}
   465       ||>> (fn x => (x, x + 1))*}
   465 
   466 
   466 text {*
   467 text {*
   467   The purpose of Line 2 is to just pair up the argument with a dummy value (since
   468   The purpose of Line 2 is to just pair up the argument with a dummy value (since
   468   @{ML "||>>"} operates on pairs). Each of the next three lines just increment 
   469   @{ML [index] "||>>"} operates on pairs). Each of the next three lines just increment 
   469   the value by one, but also nest the intrermediate results to the left. For example 
   470   the value by one, but also nest the intrermediate results to the left. For example 
   470 
   471 
   471   @{ML_response [display,gray]
   472   @{ML_response [display,gray]
   472   "acc_incs 1"
   473   "acc_incs 1"
   473   "((((\"\", 1), 2), 3), 4)"}
   474   "((((\"\", 1), 2), 3), 4)"}
   480 
   481 
   481   (FIXME: maybe give a ``real world'' example)
   482   (FIXME: maybe give a ``real world'' example)
   482 *}
   483 *}
   483 
   484 
   484 text {*
   485 text {*
   485   Recall that @{ML "|>"} is the reverse function application. Recall also that
   486   Recall that @{ML [index] "|>"} is the reverse function application. Recall also that
   486   the related 
   487   the related 
   487   reverse function composition is @{ML "#>"}. In fact all the combinators @{ML "|->"},
   488   reverse function composition is @{ML [index] "#>"}. In fact all the combinators 
   488   @{ML "|>>"} , @{ML "||>"} and @{ML "||>>"} described above have related combinators for 
   489   @{ML [index] "|->"}, @{ML [index] "|>>"} , @{ML [index] "||>"} and @{ML [index] 
   489   function composition, namely @{ML "#->"}, @{ML "#>>"}, @{ML "##>"} and @{ML "##>>"}. 
   490   "||>>"} described above have related combinators for 
   490   Using @{ML "#->"}, for example, the function @{text double} can also be written as:
   491   function composition, namely @{ML [index] "#->"}, @{ML [index] "#>>"}, 
       
   492   @{ML [index] "##>"} and @{ML [index] "##>>"}. 
       
   493   Using @{ML [index] "#->"}, for example, the function @{text double} can also be written as:
   491 *}
   494 *}
   492 
   495 
   493 ML{*val double =
   496 ML{*val double =
   494             (fn x => (x, x))
   497             (fn x => (x, x))
   495         #-> (fn x => fn y => x + y)*}
   498         #-> (fn x => fn y => x + y)*}
   522   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   525   @{ML_response [display,gray] "Context.theory_name @{theory}" "\"FirstSteps\""}
   523  
   526  
   524   where @{text "@{theory}"} is an antiquotation that is substituted with the
   527   where @{text "@{theory}"} is an antiquotation that is substituted with the
   525   current theory (remember that we assumed we are inside the theory 
   528   current theory (remember that we assumed we are inside the theory 
   526   @{text FirstSteps}). The name of this theory can be extracted using
   529   @{text FirstSteps}). The name of this theory can be extracted using
   527   the function @{ML "Context.theory_name"}. 
   530   the function @{ML [index] theory_name in Context}. 
   528 
   531 
   529   Note, however, that antiquotations are statically linked, that is their value is
   532   Note, however, that antiquotations are statically linked, that is their value is
   530   determined at ``compile-time'', not ``run-time''. For example the function
   533   determined at ``compile-time'', not ``run-time''. For example the function
   531 *}
   534 *}
   532 
   535 
   564 in
   567 in
   565   map #1 simps
   568   map #1 simps
   566 end*}
   569 end*}
   567 
   570 
   568 text {*
   571 text {*
   569   The function @{ML dest_ss in MetaSimplifier} returns a record containing all
   572   The function @{ML [index] dest_ss in MetaSimplifier} returns a record containing all
   570   information stored in the simpset, but we are only interested in the names of the
   573   information stored in the simpset, but we are only interested in the names of the
   571   simp-rules. Now you can feed in the current simpset into this function. 
   574   simp-rules. Now you can feed in the current simpset into this function. 
   572   The current simpset can be referred to using the antiquotation @{text "@{simpset}"}.
   575   The current simpset can be referred to using the antiquotation @{text "@{simpset}"}.
   573 
   576 
   574   @{ML_response_fake [display,gray] 
   577   @{ML_response_fake [display,gray] 
   585 
   588 
   586   @{ML_response [display,gray]
   589   @{ML_response [display,gray]
   587   "@{binding \"name\"}"
   590   "@{binding \"name\"}"
   588   "name"}
   591   "name"}
   589 
   592 
   590   An example where a binding is needed is the function @{ML define in
   593   An example where a binding is needed is the function @{ML [index] define in
   591   LocalTheory}.  This function is below used to define the constant @{term
   594   LocalTheory}.  This function is below used to define the constant @{term
   592   "TrueConj"} as the conjunction
   595   "TrueConj"} as the conjunction
   593   @{term "True \<and> True"}.
   596   @{term "True \<and> True"}.
   594 *}
   597 *}
   595   
   598   
   637 "@{term \"(a::nat) + b = c\"}" 
   640 "@{term \"(a::nat) + b = c\"}" 
   638 "Const (\"op =\", \<dots>) $ 
   641 "Const (\"op =\", \<dots>) $ 
   639   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   642   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   640 
   643 
   641   will show the term @{term "(a::nat) + b = c"}, but printed using the internal
   644   will show the term @{term "(a::nat) + b = c"}, but printed using the internal
   642   representation corresponding to the datatype @{ML_type "term"} defined as follows: 
   645   representation corresponding to the datatype @{ML_type [index] "term"} defined as follows: 
   643 *}  
   646 *}  
   644 
   647 
   645 ML_val %linenosgray{*datatype term =
   648 ML_val %linenosgray{*datatype term =
   646   Const of string * typ 
   649   Const of string * typ 
   647 | Free of string * typ 
   650 | Free of string * typ 
   827   Abs (\"x\", \<dots>,
   830   Abs (\"x\", \<dots>,
   828     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   831     Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ 
   829                 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   832                 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"}
   830 
   833 
   831   There are a number of handy functions that are frequently used for 
   834   There are a number of handy functions that are frequently used for 
   832   constructing terms. One is the function @{ML list_comb}, which takes a term
   835   constructing terms. One is the function @{ML [index] list_comb}, which takes a term
   833   and a list of terms as arguments, and produces as output the term
   836   and a list of terms as arguments, and produces as output the term
   834   list applied to the term. For example
   837   list applied to the term. For example
   835 
   838 
   836 @{ML_response_fake [display,gray]
   839 @{ML_response_fake [display,gray]
   837 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])"
   840 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])"
   838 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"}
   841 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"}
   839 
   842 
   840   Another handy function is @{ML lambda}, which abstracts a variable 
   843   Another handy function is @{ML [index] lambda}, which abstracts a variable 
   841   in a term. For example
   844   in a term. For example
   842   
   845   
   843   @{ML_response_fake [display,gray]
   846   @{ML_response_fake [display,gray]
   844   "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}"
   847   "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}"
   845   "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"}
   848   "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"}
   858   then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. 
   861   then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. 
   859   This is a fundamental principle
   862   This is a fundamental principle
   860   of Church-style typing, where variables with the same name still differ, if they 
   863   of Church-style typing, where variables with the same name still differ, if they 
   861   have different type.
   864   have different type.
   862 
   865 
   863   There is also the function @{ML subst_free} with which terms can 
   866   There is also the function @{ML [index] subst_free} with which terms can 
   864   be replaced by other terms. For example below, we will replace in  
   867   be replaced by other terms. For example below, we will replace in  
   865   @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0 x"} 
   868   @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0 x"} 
   866   the subterm @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0"} by @{term y}, and @{term x} by @{term True}.
   869   the subterm @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0"} by @{term y}, and @{term x} by @{term True}.
   867 
   870 
   868   @{ML_response_fake [display,gray]
   871   @{ML_response_fake [display,gray]
   878   "subst_free [(@{term \"(\<lambda>y::nat. y)\"}, @{term \"x::nat\"})] 
   881   "subst_free [(@{term \"(\<lambda>y::nat. y)\"}, @{term \"x::nat\"})] 
   879   @{term \"(\<lambda>x::nat. x)\"}"
   882   @{term \"(\<lambda>x::nat. x)\"}"
   880   "Free (\"x\", \"nat\")"}
   883   "Free (\"x\", \"nat\")"}
   881 
   884 
   882   There are many convenient functions that construct specific HOL-terms. For
   885   There are many convenient functions that construct specific HOL-terms. For
   883   example @{ML "HOLogic.mk_eq"} constructs an equality out of two terms.
   886   example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms.
   884   The types needed in this equality are calculated from the type of the
   887   The types needed in this equality are calculated from the type of the
   885   arguments. For example
   888   arguments. For example
   886 
   889 
   887 @{ML_response_fake [gray,display]
   890 @{ML_response_fake [gray,display]
   888   "writeln (Syntax.string_of_term @{context}
   891   "writeln (Syntax.string_of_term @{context}
  1004   "@{type_name \"list\"}" "\"List.list\""}
  1007   "@{type_name \"list\"}" "\"List.list\""}
  1005 
  1008 
  1006   (FIXME: Explain the following better.)
  1009   (FIXME: Explain the following better.)
  1007 
  1010 
  1008   Occasionally you have to calculate what the ``base'' name of a given
  1011   Occasionally you have to calculate what the ``base'' name of a given
  1009   constant is. For this you can use the function @{ML Sign.extern_const} or
  1012   constant is. For this you can use the function @{ML [index] extern_const in Sign} or
  1010   @{ML Long_Name.base_name}. For example:
  1013   @{ML base_name in Long_Name}. For example:
  1011 
  1014 
  1012   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
  1015   @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""}
  1013 
  1016 
  1014   The difference between both functions is that @{ML extern_const in Sign} returns
  1017   The difference between both functions is that @{ML extern_const in Sign} returns
  1015   the smallest name that is still unique, whereas @{ML base_name in Long_Name} always
  1018   the smallest name that is still unique, whereas @{ML base_name in Long_Name} always
  1031 
  1034 
  1032 *} 
  1035 *} 
  1033 
  1036 
  1034 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
  1037 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *}
  1035 
  1038 
  1036 text {* This can be equally written with the combinator @{ML "-->"} as: *}
  1039 text {* This can be equally written with the combinator @{ML [index] "-->"} as: *}
  1037 
  1040 
  1038 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
  1041 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *}
  1039 
  1042 
  1040 text {*
  1043 text {*
  1041   If you want to construct a function type with more than one argument
  1044   If you want to construct a function type with more than one argument
  1042   type, then you can use @{ML "--->"}.
  1045   type, then you can use @{ML [index] "--->"}.
  1043 *}
  1046 *}
  1044 
  1047 
  1045 ML{*fun make_fun_types tys ty = tys ---> ty *}
  1048 ML{*fun make_fun_types tys ty = tys ---> ty *}
  1046 
  1049 
  1047 text {*
  1050 text {*
  1048   A handy function for manipulating terms is @{ML map_types}: it takes a 
  1051   A handy function for manipulating terms is @{ML [index] map_types}: it takes a 
  1049   function and applies it to every type in a term. You can, for example,
  1052   function and applies it to every type in a term. You can, for example,
  1050   change every @{typ nat} in a term into an @{typ int} using the function:
  1053   change every @{typ nat} in a term into an @{typ int} using the function:
  1051 *}
  1054 *}
  1052 
  1055 
  1053 ML{*fun nat_to_int ty =
  1056 ML{*fun nat_to_int ty =
  1063 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
  1066 "map_types nat_to_int @{term \"a = (1::nat)\"}" 
  1064 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
  1067 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\")
  1065            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
  1068            $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"}
  1066 
  1069 
  1067   If you want to obtain the list of free type-variables of a term, you
  1070   If you want to obtain the list of free type-variables of a term, you
  1068   can use the function @{ML Term.add_tfrees} (similarly @{ML Term.add_tvars}
  1071   can use the function @{ML [index] add_tfrees in Term} 
  1069   for the schematic type-variables). One would expect that such functions
  1072   (similarly @{ML [index] add_tvars in Term} for the schematic type-variables). 
       
  1073   One would expect that such functions
  1070   take a term as input and return a list of types. But their type is actually 
  1074   take a term as input and return a list of types. But their type is actually 
  1071 
  1075 
  1072   @{text[display] "Term.term -> (string * Term.sort) list -> (string * Term.sort) list"}
  1076   @{text[display] "Term.term -> (string * Term.sort) list -> (string * Term.sort) list"}
  1073 
  1077 
  1074   that is they take, besides a term, also a list of type-variables as input. 
  1078   that is they take, besides a term, also a list of type-variables as input. 
  1077 
  1081 
  1078   @{ML_response [gray,display]
  1082   @{ML_response [gray,display]
  1079   "Term.add_tfrees @{term \"(a,b)\"} []"
  1083   "Term.add_tfrees @{term \"(a,b)\"} []"
  1080   "[(\"'b\", [\"HOL.type\"]), (\"'a\", [\"HOL.type\"])]"}
  1084   "[(\"'b\", [\"HOL.type\"]), (\"'a\", [\"HOL.type\"])]"}
  1081 
  1085 
  1082   The reason for this definition is that @{ML Term.add_tfrees} can
  1086   The reason for this definition is that @{ML add_tfrees in Term} can
  1083   be easily folded over a list of terms. Similarly for all functions
  1087   be easily folded over a list of terms. Similarly for all functions
  1084   named @{text "add_"}some\_name in @{ML_file "Pure/term.ML"}.
  1088   named @{text "add_"}some\_name in @{ML_file "Pure/term.ML"}.
  1085 
  1089 
  1086 *}
  1090 *}
  1087 
  1091 
  1091 text {* 
  1095 text {* 
  1092   
  1096   
  1093   You can freely construct and manipulate @{ML_type "term"}s and @{ML_type
  1097   You can freely construct and manipulate @{ML_type "term"}s and @{ML_type
  1094   typ}es, since they are just arbitrary unchecked trees. However, you
  1098   typ}es, since they are just arbitrary unchecked trees. However, you
  1095   eventually want to see if a term is well-formed, or type-checks, relative to
  1099   eventually want to see if a term is well-formed, or type-checks, relative to
  1096   a theory.  Type-checking is done via the function @{ML cterm_of}, which
  1100   a theory.  Type-checking is done via the function @{ML [index] cterm_of}, which
  1097   converts a @{ML_type term} into a @{ML_type cterm}, a \emph{certified}
  1101   converts a @{ML_type [index] term} into a @{ML_type [index] cterm}, a \emph{certified}
  1098   term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are
  1102   term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are
  1099   abstract objects that are guaranteed to be type-correct, and they can only
  1103   abstract objects that are guaranteed to be type-correct, and they can only
  1100   be constructed via ``official interfaces''.
  1104   be constructed via ``official interfaces''.
  1101 
  1105 
  1102 
  1106 
  1151   \end{exercise}
  1155   \end{exercise}
  1152 
  1156 
  1153   Remember Isabelle follows the Church-style typing for terms, i.e., a term contains 
  1157   Remember Isabelle follows the Church-style typing for terms, i.e., a term contains 
  1154   enough typing information (constants, free variables and abstractions all have typing 
  1158   enough typing information (constants, free variables and abstractions all have typing 
  1155   information) so that it is always clear what the type of a term is. 
  1159   information) so that it is always clear what the type of a term is. 
  1156   Given a well-typed term, the function @{ML type_of} returns the 
  1160   Given a well-typed term, the function @{ML [index] type_of} returns the 
  1157   type of a term. Consider for example:
  1161   type of a term. Consider for example:
  1158 
  1162 
  1159   @{ML_response [display,gray] 
  1163   @{ML_response [display,gray] 
  1160   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
  1164   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
  1161 
  1165 
  1166   @{ML_response_fake [display,gray] 
  1170   @{ML_response_fake [display,gray] 
  1167   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
  1171   "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" 
  1168   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
  1172   "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"}
  1169 
  1173 
  1170   Since the complete traversal might sometimes be too costly and
  1174   Since the complete traversal might sometimes be too costly and
  1171   not necessary, there is the function @{ML fastype_of}, which 
  1175   not necessary, there is the function @{ML [index] fastype_of}, which 
  1172   also returns the type of a term.
  1176   also returns the type of a term.
  1173 
  1177 
  1174   @{ML_response [display,gray] 
  1178   @{ML_response [display,gray] 
  1175   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
  1179   "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"}
  1176 
  1180 
  1183   where no error is detected.
  1187   where no error is detected.
  1184 
  1188 
  1185   Sometimes it is a bit inconvenient to construct a term with 
  1189   Sometimes it is a bit inconvenient to construct a term with 
  1186   complete typing annotations, especially in cases where the typing 
  1190   complete typing annotations, especially in cases where the typing 
  1187   information is redundant. A short-cut is to use the ``place-holder'' 
  1191   information is redundant. A short-cut is to use the ``place-holder'' 
  1188   type @{ML "dummyT"} and then let type-inference figure out the 
  1192   type @{ML [index] dummyT} and then let type-inference figure out the 
  1189   complete type. An example is as follows:
  1193   complete type. An example is as follows:
  1190 
  1194 
  1191   @{ML_response_fake [display,gray] 
  1195   @{ML_response_fake [display,gray] 
  1192 "let
  1196 "let
  1193   val c = Const (@{const_name \"plus\"}, dummyT) 
  1197   val c = Const (@{const_name \"plus\"}, dummyT) 
  1273   For the functions @{text "assume"}, @{text "forall_elim"} etc 
  1277   For the functions @{text "assume"}, @{text "forall_elim"} etc 
  1274   see \isccite{sec:thms}. The basic functions for theorems are defined in
  1278   see \isccite{sec:thms}. The basic functions for theorems are defined in
  1275   @{ML_file "Pure/thm.ML"}. 
  1279   @{ML_file "Pure/thm.ML"}. 
  1276   \end{readmore}
  1280   \end{readmore}
  1277 
  1281 
  1278   (FIXME: handy functions working on theorems, like @{ML ObjectLogic.rulify} and so on) 
  1282   (FIXME: handy functions working on theorems, like @{ML [index] rulify in ObjectLogic} and so on) 
  1279 
  1283 
  1280   (FIXME: how to add case-names to goal states - maybe in the 
  1284   (FIXME: how to add case-names to goal states - maybe in the 
  1281   next section)
  1285   next section)
  1282 *}
  1286 *}
  1283 
  1287 
  1290   @{ML_type "theory -> theory"}: the input theory is the current theory and the 
  1294   @{ML_type "theory -> theory"}: the input theory is the current theory and the 
  1291   output the theory where the theory attribute has been stored.
  1295   output the theory where the theory attribute has been stored.
  1292   
  1296   
  1293   This is a fundamental principle in Isabelle. A similar situation occurs 
  1297   This is a fundamental principle in Isabelle. A similar situation occurs 
  1294   for example with declaring constants. The function that declares a 
  1298   for example with declaring constants. The function that declares a 
  1295   constant on the ML-level is @{ML Sign.add_consts_i}. 
  1299   constant on the ML-level is @{ML [index] add_consts_i in Sign}. 
  1296   If you write\footnote{Recall that ML-code  needs to be 
  1300   If you write\footnote{Recall that ML-code  needs to be 
  1297   enclosed in \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}.} 
  1301   enclosed in \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}.} 
  1298 *}  
  1302 *}  
  1299 
  1303 
  1300 ML{*Sign.add_consts_i [(@{binding "BAR"}, @{typ "nat"}, NoSyn)] @{theory} *}
  1304 ML{*Sign.add_consts_i [(@{binding "BAR"}, @{typ "nat"}, NoSyn)] @{theory} *}
  1368 *}
  1372 *}
  1369 
  1373 
  1370 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  1374 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  1371 
  1375 
  1372 text {* 
  1376 text {* 
  1373   where the function @{ML "Thm.rule_attribute"} expects a function taking a 
  1377   where the function @{ML [index] rule_attribute in Thm} expects a function taking a 
  1374   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  1378   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  1375   returns another theorem (namely @{text thm} resolved with the theorem 
  1379   returns another theorem (namely @{text thm} resolved with the theorem 
  1376   @{thm [source] sym}: @{thm sym[no_vars]}).\footnote{The function @{ML RS} is explained
  1380   @{thm [source] sym}: @{thm sym[no_vars]}).\footnote{The function @{ML [index] RS} 
  1377   in Section~\ref{sec:simpletacs}.} The function 
  1381   is explained in Section~\ref{sec:simpletacs}.} The function 
  1378   @{ML "Thm.rule_attribute"} then returns 
  1382   @{ML rule_attribute in Thm} then returns  an attribute.
  1379   an attribute.
       
  1380 
  1383 
  1381   Before we can use the attribute, we need to set it up. This can be done
  1384   Before we can use the attribute, we need to set it up. This can be done
  1382   using the Isabelle command \isacommand{attribute\_setup} as follows:
  1385   using the Isabelle command \isacommand{attribute\_setup} as follows:
  1383 *}
  1386 *}
  1384 
  1387 
  1409   \begin{isabelle}
  1412   \begin{isabelle}
  1410   \isacommand{thm}~@{text "test[my_sym]"}\\
  1413   \isacommand{thm}~@{text "test[my_sym]"}\\
  1411   @{text "> "}~@{thm test[my_sym]}
  1414   @{text "> "}~@{thm test[my_sym]}
  1412   \end{isabelle}
  1415   \end{isabelle}
  1413 
  1416 
  1414   An alternative for setting up an attribute is the function @{ML Attrib.setup}.
  1417   An alternative for setting up an attribute is the function @{ML [index] setup in Attrib}.
  1415   So instead of using \isacommand{attribute\_setup}, you can also set up the
  1418   So instead of using \isacommand{attribute\_setup}, you can also set up the
  1416   attribute as follows:
  1419   attribute as follows:
  1417 *}
  1420 *}
  1418 
  1421 
  1419 ML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric)
  1422 ML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric)
  1432 ML{*fun MY_THEN thms = 
  1435 ML{*fun MY_THEN thms = 
  1433   Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*}
  1436   Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*}
  1434 
  1437 
  1435 text {* 
  1438 text {* 
  1436   where @{ML swap} swaps the components of a pair. The setup of this theorem
  1439   where @{ML swap} swaps the components of a pair. The setup of this theorem
  1437   attribute uses the parser @{ML Attrib.thms}, which parses a list of
  1440   attribute uses the parser @{ML thms in Attrib}, which parses a list of
  1438   theorems. 
  1441   theorems. 
  1439 *}
  1442 *}
  1440 
  1443 
  1441 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} 
  1444 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} 
  1442   "resolving the list of theorems with the proved theorem"
  1445   "resolving the list of theorems with the proved theorem"
  1474   \end{isabelle}
  1477   \end{isabelle}
  1475 
  1478 
  1476   you get an exception indicating that the theorem @{thm [source] sym}
  1479   you get an exception indicating that the theorem @{thm [source] sym}
  1477   does not resolve with meta-equations. 
  1480   does not resolve with meta-equations. 
  1478 
  1481 
  1479   The purpose of @{ML Thm.rule_attribute} is to directly manipulate theorems.
  1482   The purpose of @{ML [index] rule_attribute in Thm} is to directly manipulate theorems.
  1480   Another usage of theorem attributes is to add and delete theorems from stored data.
  1483   Another usage of theorem attributes is to add and delete theorems from stored data.
  1481   For example the theorem attribute @{text "[simp]"} adds or deletes a theorem from the
  1484   For example the theorem attribute @{text "[simp]"} adds or deletes a theorem from the
  1482   current simpset. For these applications, you can use @{ML Thm.declaration_attribute}. 
  1485   current simpset. For these applications, you can use @{ML [index] declaration_attribute in Thm}. 
  1483   To illustrate this function, let us introduce a reference containing a list
  1486   To illustrate this function, let us introduce a reference containing a list
  1484   of theorems.
  1487   of theorems.
  1485 *}
  1488 *}
  1486 
  1489 
  1487 ML{*val my_thms = ref ([] : thm list)*}
  1490 ML{*val my_thms = ref ([] : thm list)*}
  1504   (my_thms := Thm.del_thm thm (!my_thms); ctxt)*}
  1507   (my_thms := Thm.del_thm thm (!my_thms); ctxt)*}
  1505 
  1508 
  1506 text {*
  1509 text {*
  1507   These functions take a theorem and a context and, for what we are explaining
  1510   These functions take a theorem and a context and, for what we are explaining
  1508   here it is sufficient that they just return the context unchanged. They change
  1511   here it is sufficient that they just return the context unchanged. They change
  1509   however the reference @{ML my_thms}, whereby the function @{ML Thm.add_thm}
  1512   however the reference @{ML my_thms}, whereby the function 
  1510   adds a theorem if it is not already included in the list, and @{ML
  1513   @{ML [index] add_thm in Thm} adds a theorem if it is not already included in 
  1511   Thm.del_thm} deletes one (both functions use the predicate @{ML
  1514   the list, and @{ML [index] del_thm in Thm} deletes one (both functions use the 
  1512   Thm.eq_thm_prop}, which compares theorems according to their proved
  1515   predicate @{ML [index] eq_thm_prop in Thm}, which compares theorems according to 
  1513   propositions modulo alpha-equivalence).
  1516   their proved propositions modulo alpha-equivalence).
  1514 
       
  1515 
  1517 
  1516   You can turn functions @{ML my_thm_add} and @{ML my_thm_del} into 
  1518   You can turn functions @{ML my_thm_add} and @{ML my_thm_del} into 
  1517   attributes with the code
  1519   attributes with the code
  1518 *}
  1520 *}
  1519 
  1521 
  1526 
  1528 
  1527 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} 
  1529 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} 
  1528   "maintaining a list of my_thms - rough test only!" 
  1530   "maintaining a list of my_thms - rough test only!" 
  1529 
  1531 
  1530 text {*
  1532 text {*
  1531   The parser @{ML Attrib.add_del} is a pre-defined parser for 
  1533   The parser @{ML [index] add_del in Attrib} is a pre-defined parser for 
  1532   adding and deleting lemmas. Now if you prove the next lemma 
  1534   adding and deleting lemmas. Now if you prove the next lemma 
  1533   and attach to it the attribute @{text "[my_thms]"}
  1535   and attach to it the attribute @{text "[my_thms]"}
  1534 *}
  1536 *}
  1535 
  1537 
  1536 lemma trueI_2[my_thms]: "True" by simp
  1538 lemma trueI_2[my_thms]: "True" by simp
  1554   @{ML_response_fake [display,gray]
  1556   @{ML_response_fake [display,gray]
  1555   "!my_thms"
  1557   "!my_thms"
  1556   "[\"True\", \"Suc (Suc 0) = 2\"]"}
  1558   "[\"True\", \"Suc (Suc 0) = 2\"]"}
  1557 
  1559 
  1558   The theorem @{thm [source] trueI_2} only appears once, since the 
  1560   The theorem @{thm [source] trueI_2} only appears once, since the 
  1559   function @{ML Thm.add_thm} tests for duplicates, before extending
  1561   function @{ML [index] add_thm in Thm} tests for duplicates, before extending
  1560   the list. Deletion from the list works as follows:
  1562   the list. Deletion from the list works as follows:
  1561 *}
  1563 *}
  1562 
  1564 
  1563 declare test[my_thms del]
  1565 declare test[my_thms del]
  1564 
  1566 
  1566 
  1568 
  1567   @{ML_response_fake [display,gray]
  1569   @{ML_response_fake [display,gray]
  1568   "!my_thms"
  1570   "!my_thms"
  1569   "[\"True\"]"}
  1571   "[\"True\"]"}
  1570 
  1572 
  1571   We used in this example two functions declared as @{ML Thm.declaration_attribute}, 
  1573   We used in this example two functions declared as @{ML [index] declaration_attribute in Thm}, 
  1572   but there can be any number of them. We just have to change the parser for reading
  1574   but there can be any number of them. We just have to change the parser for reading
  1573   the arguments accordingly. 
  1575   the arguments accordingly. 
  1574 
  1576 
  1575   However, as said at the beginning of this example, using references for storing theorems is
  1577   However, as said at the beginning of this example, using references for storing theorems is
  1576   \emph{not} the received way of doing such things. The received way is to 
  1578   \emph{not} the received way of doing such things. The received way is to 
  1630 
  1632 
  1631   With theorem attribute @{text my_thms2} you can also nicely see why it 
  1633   With theorem attribute @{text my_thms2} you can also nicely see why it 
  1632   is important to 
  1634   is important to 
  1633   store data in a ``data slot'' and \emph{not} in a reference. Backtrack
  1635   store data in a ``data slot'' and \emph{not} in a reference. Backtrack
  1634   to the point just before the lemma @{thm [source] three} was proved and 
  1636   to the point just before the lemma @{thm [source] three} was proved and 
  1635   check the the content of @{ML_struct "MyThmsData"}: it should be empty. 
  1637   check the the content of @{ML_struct MyThmsData}: it should be empty. 
  1636   The addition has been properly retracted. Now consider the proof:
  1638   The addition has been properly retracted. Now consider the proof:
  1637 *}
  1639 *}
  1638 
  1640 
  1639 lemma four[my_thms]: "4 = Suc (Suc (Suc (Suc 0)))" by simp
  1641 lemma four[my_thms]: "4 = Suc (Suc (Suc (Suc 0)))" by simp
  1640 
  1642 
  1797 ML {* LocalTheory.set_group *}
  1799 ML {* LocalTheory.set_group *}
  1798 *)
  1800 *)
  1799 
  1801 
  1800 section {* Storing Theorems\label{sec:storing} (TBD) *}
  1802 section {* Storing Theorems\label{sec:storing} (TBD) *}
  1801 
  1803 
  1802 text {* @{ML PureThy.add_thms_dynamic} *}
  1804 text {* @{ML [index] add_thms_dynamic in PureThy} *}
  1803 
  1805 
  1804 local_setup {* 
  1806 local_setup {* 
  1805   LocalTheory.note Thm.theoremK 
  1807   LocalTheory.note Thm.theoremK 
  1806     ((@{binding "allI_alt"}, []), [@{thm allI}]) #> snd *}
  1808     ((@{binding "allI_alt"}, []), [@{thm allI}]) #> snd *}
  1807 
  1809 
  1843   sophisticated, Isabelle includes an infrastructure for properly formatting text.
  1845   sophisticated, Isabelle includes an infrastructure for properly formatting text.
  1844   This infrastructure is loosely based on a paper by Oppen~\cite{Oppen80}. Most of
  1846   This infrastructure is loosely based on a paper by Oppen~\cite{Oppen80}. Most of
  1845   its functions do not operate on @{ML_type string}s, but on instances of the
  1847   its functions do not operate on @{ML_type string}s, but on instances of the
  1846   type:
  1848   type:
  1847 
  1849 
  1848   @{ML_type [display, gray] "Pretty.T"}
  1850   @{ML_type [display, gray, index] "Pretty.T"}
  1849 
  1851 
  1850   The function @{ML "Pretty.str"} transforms a (plain) string into such a pretty 
  1852   The function @{ML str in Pretty} transforms a (plain) string into such a pretty 
  1851   type. For example
  1853   type. For example
  1852 
  1854 
  1853   @{ML_response_fake [display,gray]
  1855   @{ML_response_fake [display,gray]
  1854   "Pretty.str \"test\"" "String (\"test\", 4)"}
  1856   "Pretty.str \"test\"" "String (\"test\", 4)"}
  1855 
  1857 
  1856   where the result indicates that we transformed a string with length 4. Once
  1858   where the result indicates that we transformed a string with length 4. Once
  1857   you have a pretty type, you can, for example, control where linebreaks may
  1859   you have a pretty type, you can, for example, control where linebreaks may
  1858   occur in case the text wraps over a line, or with how much indentation a
  1860   occur in case the text wraps over a line, or with how much indentation a
  1859   text should be printed.  However, if you want to actually output the
  1861   text should be printed.  However, if you want to actually output the
  1860   formatted text, you have to transform the pretty type back into a @{ML_type
  1862   formatted text, you have to transform the pretty type back into a @{ML_type
  1861   string}. This can be done with the function @{ML Pretty.string_of}. In what
  1863   string}. This can be done with the function @{ML [index] string_of in Pretty}. In what
  1862   follows we will use the following wrapper function for printing a pretty
  1864   follows we will use the following wrapper function for printing a pretty
  1863   type:
  1865   type:
  1864 *}
  1866 *}
  1865 
  1867 
  1866 ML{*fun pprint prt = writeln (Pretty.string_of prt)*}
  1868 ML{*fun pprint prt = writeln (Pretty.string_of prt)*}
  1901 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo
  1903 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo
  1902 oooooooooooooobaaaaaaaaaaaar"}
  1904 oooooooooooooobaaaaaaaaaaaar"}
  1903 
  1905 
  1904   However by using pretty types you have the ability to indicate a possible
  1906   However by using pretty types you have the ability to indicate a possible
  1905   linebreak for example at each space. You can achieve this with the function
  1907   linebreak for example at each space. You can achieve this with the function
  1906   @{ML Pretty.breaks}, which expects a list of pretty types and inserts a
  1908   @{ML [index] breaks in Pretty}, which expects a list of pretty types and inserts a
  1907   possible linebreak in between every two elements in this list. To print
  1909   possible linebreak in between every two elements in this list. To print
  1908   this list of pretty types as a single string, we concatenate them 
  1910   this list of pretty types as a single string, we concatenate them 
  1909   with the function @{ML Pretty.blk} as follows:
  1911   with the function @{ML [index] blk in Pretty} as follows:
  1910 
  1912 
  1911 
  1913 
  1912 @{ML_response_fake [display,gray]
  1914 @{ML_response_fake [display,gray]
  1913 "let
  1915 "let
  1914   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1916   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1919 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar 
  1921 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar 
  1920 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1922 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1921 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1923 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1922 
  1924 
  1923   Here the layout of @{ML test_str} is much more pleasing to the 
  1925   Here the layout of @{ML test_str} is much more pleasing to the 
  1924   eye. The @{ML "0"} in @{ML Pretty.blk} stands for no indentation
  1926   eye. The @{ML "0"} in @{ML [index] blk in Pretty} stands for no indentation
  1925   of the printed string. You can increase the indentation and obtain
  1927   of the printed string. You can increase the indentation and obtain
  1926   
  1928   
  1927 @{ML_response_fake [display,gray]
  1929 @{ML_response_fake [display,gray]
  1928 "let
  1930 "let
  1929   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1931   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1935    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1937    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1936    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1938    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1937 
  1939 
  1938   where starting from the second line the indent is 3. If you want
  1940   where starting from the second line the indent is 3. If you want
  1939   that every line starts with the same indent, you can use the
  1941   that every line starts with the same indent, you can use the
  1940   function @{ML Pretty.indent} as follows:
  1942   function @{ML [index] indent in Pretty} as follows:
  1941 
  1943 
  1942 @{ML_response_fake [display,gray]
  1944 @{ML_response_fake [display,gray]
  1943 "let
  1945 "let
  1944   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1946   val ptrs = map Pretty.str (space_explode \" \" test_str)
  1945 in
  1947 in
  1950           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1952           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar
  1951           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1953           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"}
  1952 
  1954 
  1953   If you want to print out a list of items separated by commas and 
  1955   If you want to print out a list of items separated by commas and 
  1954   have the linebreaks handled properly, you can use the function 
  1956   have the linebreaks handled properly, you can use the function 
  1955   @{ML Pretty.commas}. For example
  1957   @{ML [index] commas in Pretty}. For example
  1956 
  1958 
  1957 @{ML_response_fake [display,gray]
  1959 @{ML_response_fake [display,gray]
  1958 "let
  1960 "let
  1959   val ptrs = map (Pretty.str o string_of_int) (99998 upto 100020)
  1961   val ptrs = map (Pretty.str o string_of_int) (99998 upto 100020)
  1960 in
  1962 in
  1965 100016, 100017, 100018, 100019, 100020"}
  1967 100016, 100017, 100018, 100019, 100020"}
  1966 
  1968 
  1967   where @{ML upto} generates a list of integers. You can print this
  1969   where @{ML upto} generates a list of integers. You can print this
  1968   list out as an ``set'', that means enclosed inside @{text [quotes] "{"} and
  1970   list out as an ``set'', that means enclosed inside @{text [quotes] "{"} and
  1969   @{text [quotes] "}"}, and separated by commas using the function
  1971   @{text [quotes] "}"}, and separated by commas using the function
  1970   @{ML Pretty.enum}. For example
  1972   @{ML [index] enum in Pretty}. For example
  1971 *}
  1973 *}
  1972 
  1974 
  1973 text {*
  1975 text {*
  1974   
  1976   
  1975 @{ML_response_fake [display,gray]
  1977 @{ML_response_fake [display,gray]
  2036 end*}
  2038 end*}
  2037 
  2039 
  2038 text {*
  2040 text {*
  2039   In Line 3 we define a function that inserts according to spaces 
  2041   In Line 3 we define a function that inserts according to spaces 
  2040   possible linebreaks into an (English). In Lines 4 and 5 we pretty-print
  2042   possible linebreaks into an (English). In Lines 4 and 5 we pretty-print
  2041   the term and its type using the functions @{ML Syntax.pretty_term} and
  2043   the term and its type using the functions @{ML [index] pretty_term in Syntax} and
  2042   @{ML Syntax.pretty_typ}. We also use the function @{ML Pretty.quote}
  2044   @{ML [index] pretty_typ in Syntax}. We also use the function @{ML [index] quote in Pretty}
  2043   in order to enclose the term and type inside quotation marks. In Line 
  2045   in order to enclose the term and type inside quotation marks. In Line 
  2044   9 we add a period right after the type without the possibility of a 
  2046   9 we add a period right after the type without the possibility of a 
  2045   linebreak, because we do not want that a linebreak occurs there.
  2047   linebreak, because we do not want that a linebreak occurs there.
  2046 
  2048 
  2047   Now you can write
  2049   Now you can write