diff -r 6103b0eadbf2 -r f7c97e64cc2a ProgTutorial/Essential.thy --- a/ProgTutorial/Essential.thy Tue May 14 17:45:13 2019 +0200 +++ b/ProgTutorial/Essential.thy Thu May 16 19:56:12 2019 +0200 @@ -27,7 +27,7 @@ Uncertified terms are often just called terms. One way to construct them is by using the antiquotation \mbox{\@{term \}\}. For example - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "@{term \"(a::nat) + b = c\"}" "Const (\"HOL.eq\", _) $ (Const (\"Groups.plus_class.plus\", _) $ _ $ _) $ _"} @@ -53,7 +53,7 @@ terms use the usual de Bruijn index mechanism for representing bound variables. For example in - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "@{term \"\x y. x y\"}" "Abs (\"x\", \"'a \ 'b\", Abs (\"y\", \"'a\", Bound 1 $ Bound 0))"} @@ -69,7 +69,7 @@ Be careful if you pretty-print terms. Consider pretty-printing the abstraction term shown above: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "@{term \"\x y. x y\"} |> pretty_term @{context} |> pwriteln" @@ -79,7 +79,7 @@ tacitly eta-contracted the output. You obtain a similar result with beta-redexes - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val redex = @{term \"(\(x::int) (y::int). x)\"} val arg1 = @{term \"1::int\"} @@ -97,7 +97,7 @@ value @{ML_ind show_abbrevs in Syntax}. For example - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val redex = @{term \"(\(x::int) (y::int). x)\"} val arg1 = @{term \"1::int\"} @@ -114,7 +114,7 @@ \emph{schematic} variables (term-constructor @{ML Var} and written with a leading question mark). Consider the following two examples - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val v1 = Var ((\"x\", 3), @{typ bool}) val v2 = Var ((\"x1\", 3), @{typ bool}) @@ -144,14 +144,14 @@ Constructing terms via antiquotations has the advantage that only typable terms can be constructed. For example - @{ML_response_fake_both [display,gray] + @{ML_matchresult_fake_both [display,gray] "@{term \"x x\"}" "Type unification failed: Occurs check!"} raises a typing error, while it is perfectly ok to construct the term with the raw ML-constructors: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val omega = Free (\"x\", @{typ \"nat \ nat\"}) $ Free (\"x\", @{typ nat}) in @@ -186,13 +186,13 @@ usually invisible \Trueprop\-coercions whenever necessary. Consider for example the pairs -@{ML_response [display,gray] "(@{term \"P x\"}, @{prop \"P x\"})" +@{ML_matchresult [display,gray] "(@{term \"P x\"}, @{prop \"P x\"})" "(Free (\"P\", _) $ Free (\"x\", _), Const (\"HOL.Trueprop\", _) $ (Free (\"P\", _) $ Free (\"x\", _)))"} where a coercion is inserted in the second component and - @{ML_response [display,gray] "(@{term \"P x \ Q x\"}, @{prop \"P x \ Q x\"})" + @{ML_matchresult [display,gray] "(@{term \"P x \ Q x\"}, @{prop \"P x \ Q x\"})" "(Const (\"Pure.imp\", _) $ _ $ _, Const (\"Pure.imp\", _) $ _ $ _)"} @@ -204,7 +204,7 @@ As already seen above, types can be constructed using the antiquotation \@{typ _}\. For example: - @{ML_response_fake [display,gray] "@{typ \"bool \ nat\"}" "bool \ nat"} + @{ML_matchresult_fake [display,gray] "@{typ \"bool \ nat\"}" "bool \ nat"} The corresponding datatype is \ @@ -224,7 +224,7 @@ example, because Isabelle always pretty prints types (unlike terms). Using just the antiquotation \@{typ "bool"}\ we only see - @{ML_response [display, gray] + @{ML_matchresult [display, gray] "@{typ \"bool\"}" "bool"} which is the pretty printed version of \bool\. However, in PolyML @@ -263,13 +263,13 @@ text \ Now the type bool is printed out in full detail. - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "@{typ \"bool\"}" "Type (\"HOL.bool\", [])"} When printing out a list-type - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "@{typ \"'a list\"}" "Type (\"List.list\", [TFree (\"'a\", [\"HOL.type\"])])"} @@ -279,7 +279,7 @@ \fun\ is defined in the theory \HOL\, it is still represented by its simple name. - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "@{typ \"bool \ nat\"}" "Type (\"fun\", [Type (\"HOL.bool\", []), Type (\"Nat.nat\", [])])"} @@ -294,7 +294,7 @@ After that the types for booleans, lists and so on are printed out again the standard Isabelle way. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "@{typ \"bool\"}; @{typ \"'a list\"}" "\"bool\" @@ -338,7 +338,7 @@ to both functions. With @{ML make_imp} you obtain the intended term involving the given arguments - @{ML_response [display,gray] "make_imp @{term S} @{term T}" + @{ML_matchresult [display,gray] "make_imp @{term S} @{term T}" "Const _ $ Abs (\"x\", Type (\"Nat.nat\",[]), Const _ $ (Free (\"S\",_) $ _) $ (Free (\"T\",_) $ _))"} @@ -346,7 +346,7 @@ whereas with @{ML make_wrong_imp} you obtain a term involving the @{term "P"} and \Q\ from the antiquotation. - @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T}" + @{ML_matchresult [display,gray] "make_wrong_imp @{term S} @{term T}" "Const _ $ Abs (\"x\", _, Const _ $ (Const _ $ (Free (\"P\",_) $ _)) $ @@ -358,7 +358,7 @@ term list applied to the term. For example -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val trm = @{term \"P::bool \ bool \ bool\"} val args = [@{term \"True\"}, @{term \"False\"}] @@ -371,7 +371,7 @@ Another handy function is @{ML_ind lambda in Term}, which abstracts a variable in a term. For example - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val x_nat = @{term \"x::nat\"} val trm = @{term \"(P::nat \ bool) x\"} @@ -387,7 +387,7 @@ is of the same type as the abstracted variable. If it is of different type, as in - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val x_int = @{term \"x::int\"} val trm = @{term \"(P::nat \ bool) x\"} @@ -406,7 +406,7 @@ "(f::nat \ nat \ nat) 0 x"} the subterm @{term "(f::nat \ nat \ nat) 0"} by @{term y}, and @{term x} by @{term True}. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val sub1 = (@{term \"(f::nat \ nat \ nat) 0\"}, @{term \"y::nat \ nat\"}) val sub2 = (@{term \"x::nat\"}, @{term \"True\"}) @@ -419,7 +419,7 @@ As can be seen, @{ML subst_free} does not take typability into account. However it takes alpha-equivalence into account: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val sub = (@{term \"(\y::nat. y)\"}, @{term \"x::nat\"}) val trm = @{term \"(\x::nat. x)\"} @@ -446,7 +446,7 @@ The function returns a pair consisting of the stripped off variables and the body of the universal quantification. For example - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "strip_alls @{term \"\x y. x = (y::bool)\"}" "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")], Const (\"op =\", _) $ Bound 1 $ Bound 0)"} @@ -466,7 +466,7 @@ bound variables. With the function @{ML subst_bounds}, you can replace these loose @{ML_ind Bound in Term}s with the stripped off variables. - @{ML_response_fake [display, gray, linenos] + @{ML_matchresult_fake [display, gray, linenos] "let val (vrs, trm) = strip_alls @{term \"\x y. x = (y::bool)\"} in @@ -488,7 +488,7 @@ the loose de Bruijn index is replaced by a unique free variable. For example - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val body = Bound 0 $ Free (\"x\", @{typ nat}) in @@ -501,7 +501,7 @@ @{ML_ind incr_boundvars in Term}, increases by an integer the indices of the loose bound variables in a term. In the code below -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "@{term \"\x y z u. z = u\"} |> strip_alls ||> incr_boundvars 2 @@ -519,7 +519,7 @@ The second function, @{ML_ind loose_bvar1 in Text}, tests whether a term contains a loose bound of a certain index. For example - @{ML_response_fake [gray,display] + @{ML_matchresult_fake [gray,display] "let val body = snd (strip_alls @{term \"\x y. x = (y::bool)\"}) in @@ -530,11 +530,11 @@ "[true, true, false]"} There are also many convenient functions that construct specific HOL-terms - in the structure @{ML_struct HOLogic}. For example @{ML_ind mk_eq in + in the structure @{ML_structure HOLogic}. For example @{ML_ind mk_eq in HOLogic} constructs an equality out of two terms. The types needed in this equality are calculated from the type of the arguments. For example -@{ML_response_fake [gray,display] +@{ML_matchresult_fake [gray,display] "let val eq = HOLogic.mk_eq (@{term \"True\"}, @{term \"False\"}) in @@ -569,7 +569,7 @@ text \ will not correctly match the formula @{prop[source] "\x::nat. P x"}: - @{ML_response [display,gray] "is_all @{term \"\x::nat. P x\"}" "false"} + @{ML_matchresult [display,gray] "is_all @{term \"\x::nat. P x\"}" "false"} The problem is that the \@term\-antiquotation in the pattern fixes the type of the constant @{term "All"} to be @{typ "('a \ bool) \ bool"} for @@ -583,7 +583,7 @@ text \ because now - @{ML_response [display,gray] "is_all @{term \"\x::nat. P x\"}" "true"} + @{ML_matchresult [display,gray] "is_all @{term \"\x::nat. P x\"}" "true"} matches correctly (the first wildcard in the pattern matches any type and the second any term). @@ -598,14 +598,14 @@ text \ Unfortunately, also this function does \emph{not} work as expected, since - @{ML_response [display,gray] "is_nil @{term \"Nil\"}" "false"} + @{ML_matchresult [display,gray] "is_nil @{term \"Nil\"}" "false"} The problem is that on the ML-level the name of a constant is more subtle than you might expect. The function @{ML is_all} worked correctly, because @{term "All"} is such a fundamental constant, which can be referenced by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at - @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", _)"} + @{ML_matchresult [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", _)"} the name of the constant \Nil\ depends on the theory in which the term constructor is defined (\List\) and also in which datatype @@ -613,7 +613,7 @@ type-classes. Consider for example the constants for @{term "zero"} and \mbox{@{term "times"}}: - @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"times\"})" + @{ML_matchresult [display,gray] "(@{term \"0::nat\"}, @{term \"times\"})" "(Const (\"Groups.zero_class.zero\", _), Const (\"Groups.times_class.times\", _))"} @@ -636,7 +636,7 @@ The antiquotation for properly referencing type constants is \@{type_name \}\. For example - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "@{type_name \"list\"}" "\"List.list\""} Although types of terms can often be inferred, there are many @@ -674,7 +674,7 @@ text \ Here is an example: -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "map_types nat_to_int @{term \"a = (1::nat)\"}" "Const (\"op =\", \"int \ int \ bool\") $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} @@ -691,7 +691,7 @@ So in order to obtain the list of type-variables of a term you have to call them as follows - @{ML_response [gray,display] + @{ML_matchresult [gray,display] "Term.add_tfrees @{term \"(a, b)\"} []" "[(\"'b\", [\"HOL.type\"]), (\"'a\", [\"HOL.type\"])]"} @@ -776,7 +776,7 @@ Let us begin with describing the unification and matching functions for types. Both return type environments (ML-type @{ML_type "Type.tyenv"}) which map schematic type variables to types and sorts. Below we use the - function @{ML_ind typ_unify in Sign} from the structure @{ML_struct Sign} + function @{ML_ind typ_unify in Sign} from the structure @{ML_structure Sign} for unifying the types \?'a * ?'b\ and \?'b list * nat\. This will produce the mapping, or type environment, \[?'a := ?'b list, ?'b := nat]\. @@ -796,9 +796,9 @@ below. In case of failure, @{ML typ_unify in Sign} will raise the exception \TUNIFY\. We can print out the resulting type environment bound to @{ML tyenv_unif} with the built-in function @{ML_ind dest in Vartab} from the - structure @{ML_struct Vartab}. - - @{ML_response_fake [display,gray] + structure @{ML_structure Vartab}. + + @{ML_matchresult_fake [display,gray] "Vartab.dest tyenv_unif" "[((\"'a\", 0), ([\"HOL.type\"], \"?'b List.list\")), ((\"'b\", 0), ([\"HOL.type\"], \"nat\"))]"} @@ -839,7 +839,7 @@ environment in the example this function prints out the more legible: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "pretty_tyenv @{context} tyenv_unif" "[?'a := ?'b list, ?'b := nat]"} @@ -882,7 +882,7 @@ of sort information by setting @{ML_ind show_sorts in Syntax} to true. This allows us to inspect the typing environment. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "pretty_tyenv @{context} tyenv" "[?'a::s1 := ?'a1::{s1, s2}, ?'b::s2 := ?'a1::{s1, s2}]"} @@ -891,7 +891,7 @@ type variable has been introduced the @{ML index}, originally being \0\, has been increased to \1\. - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "index" "1"} @@ -899,7 +899,7 @@ \?'b list * nat\ from the beginning of this section, and the calculated type environment @{ML tyenv_unif}: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "pretty_tyenv @{context} tyenv_unif" "[?'a := ?'b list, ?'b := nat]"} @@ -911,12 +911,12 @@ performance reasons. To apply such a type environment to a type, say \?'a * ?'b\, you should use the function @{ML_ind norm_type in Envir}: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Envir.norm_type tyenv_unif @{typ_pat \"?'a * ?'b\"}" "nat list * nat"} Matching of types can be done with the function @{ML_ind typ_match in Sign} - also from the structure @{ML_struct Sign}. This function returns a @{ML_type + also from the structure @{ML_structure Sign}. This function returns a @{ML_type Type.tyenv} as well, but might raise the exception \TYPE_MATCH\ in case of failure. For example \ @@ -931,7 +931,7 @@ text \ Printing out the calculated matcher gives - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "pretty_tyenv @{context} tyenv_match" "[?'a := bool list, ?'b := nat]"} @@ -939,7 +939,7 @@ applying the matcher to a type needs to be done with the function @{ML_ind subst_type in Envir}. For example - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Envir.subst_type tyenv_match @{typ_pat \"?'a * ?'b\"}" "bool list * nat"} @@ -960,14 +960,14 @@ Now @{ML tyenv_unif} is equal to @{ML tyenv_match'}. If we apply @{ML norm_type in Envir} to the type \?'a * ?'b\ we obtain - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Envir.norm_type tyenv_match' @{typ_pat \"?'a * ?'b\"}" "nat list * nat"} which does not solve the matching problem, and if we apply @{ML subst_type in Envir} to the same type we obtain - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Envir.subst_type tyenv_unif @{typ_pat \"?'a * ?'b\"}" "?'b list * nat"} @@ -1023,7 +1023,7 @@ the type environment is empty and can be ignored. The resulting term environment is - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "pretty_env @{context} fo_env" "[?X := P, ?Y := \a b. Q b a]"} @@ -1033,7 +1033,7 @@ unifiers). The function @{ML subst_term in Envir} expects a type environment, which is set to empty in the example below, and a term environment. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val trm = @{term_pat \"(?X::(nat\nat\nat)\bool) ?Y\"} in @@ -1050,7 +1050,7 @@ matching \\x. P x\ against the pattern \\y. ?X y\. In this case, first-order matching produces \[?X := P]\. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "let val fo_pat = @{term_pat \"\y. (?X::nat\bool) y\"} val trm = @{term \"\x. (P::nat\bool) x\"} @@ -1071,11 +1071,11 @@ In particular this excludes terms where a schematic variable is an argument of another one and where a schematic variable is applied twice with the same bound variable. The function - @{ML_ind pattern in Pattern} in the structure @{ML_struct Pattern} tests + @{ML_ind pattern in Pattern} in the structure @{ML_structure Pattern} tests whether a term satisfies these restrictions under the assumptions that it is beta-normal, well-typed and has no loose bound variables. - @{ML_response [display, gray] + @{ML_matchresult [display, gray] "let val trm_list = [@{term_pat \"?X\"}, @{term_pat \"a\"}, @@ -1099,9 +1099,9 @@ record of type @{ML_type Envir.env} containing a max-index, a type environment and a term environment). The corresponding functions are @{ML_ind match in Pattern} and @{ML_ind unify in Pattern}, both implemented in the structure - @{ML_struct Pattern}. An example for higher-order pattern unification is - - @{ML_response_fake [display, gray] + @{ML_structure Pattern}. An example for higher-order pattern unification is + + @{ML_matchresult_fake [display, gray] "let val trm1 = @{term_pat \"\x y. g (?X y x) (f (?Y x))\"} val trm2 = @{term_pat \"\u v. g u (f u)\"} @@ -1152,7 +1152,7 @@ We can print them out as follows. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "pretty_env @{context} (Envir.term_env un1); pretty_env @{context} (Envir.term_env un2); pretty_env @{context} (Envir.term_env un3)" @@ -1164,7 +1164,7 @@ In case of failure the function @{ML_ind unifiers in Unify} does not raise an exception, rather returns the empty sequence. For example - @{ML_response [display, gray] + @{ML_matchresult [display, gray] "let val trm1 = @{term \"a\"} val trm2 = @{term \"b\"} @@ -1181,7 +1181,7 @@ called. This function has a built-in bound, which can be accessed and manipulated as a configuration value. For example - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Config.get_global @{theory} (Unify.search_bound)" "Int 60"} @@ -1192,7 +1192,7 @@ For higher-order matching the function is called @{ML_ind matchers in Unify} - implemented in the structure @{ML_struct Unify}. Also this function returns + implemented in the structure @{ML_structure Unify}. Also this function returns sequences with possibly more than one matcher. Like @{ML unifiers in Unify}, this function does not raise an exception in case of failure, but returns an empty sequence. It also first tries out whether the matching @@ -1213,7 +1213,7 @@ this problem is to instantiate the schematic variables \?P\ and \?x\. Instantiation function for theorems is @{ML_ind instantiate_normalize in Drule} from the structure - @{ML_struct Drule}. One problem, however, is + @{ML_structure Drule}. One problem, however, is that this function expects the instantiations as lists of @{ML_type "((indexname * sort) * ctyp)"} respective @{ML_type "(indexname * typ) * cterm"}: @@ -1266,7 +1266,7 @@ @{term "Q True"}. - @{ML_response_fake [gray,display,linenos] + @{ML_matchresult_fake [gray,display,linenos] "let val pat = Logic.strip_imp_concl (Thm.prop_of @{thm spec}) val trm = @{term \"Trueprop (Q True)\"} @@ -1354,14 +1354,14 @@ Given a well-typed term, the function @{ML_ind type_of in Term} returns the type of a term. Consider for example: - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "type_of (@{term \"f::nat \ bool\"} $ @{term \"x::nat\"})" "bool"} To calculate the type, this function traverses the whole term and will detect any typing inconsistency. For example changing the type of the variable @{term "x"} from @{typ "nat"} to @{typ "int"} will result in the error message: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "type_of (@{term \"f::nat \ bool\"} $ @{term \"x::int\"})" "*** Exception- TYPE (\"type_of: type mismatch in application\" \"} @@ -1369,13 +1369,13 @@ not necessary, there is the function @{ML_ind fastype_of in Term}, which also returns the type of a term. - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "fastype_of (@{term \"f::nat \ bool\"} $ @{term \"x::nat\"})" "bool"} However, efficiency is gained on the expense of skipping some tests. You can see this in the following example - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "fastype_of (@{term \"f::nat \ bool\"} $ @{term \"x::int\"})" "bool"} where no error is detected. @@ -1387,7 +1387,7 @@ complete type. The type inference can be invoked with the function @{ML_ind check_term in Syntax}. An example is as follows: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val c = Const (@{const_name \"plus\"}, dummyT) val o = @{term \"1::nat\"} @@ -1432,26 +1432,26 @@ Certification is always relative to a context. For example you can write: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Thm.cterm_of @{context} @{term \"(a::nat) + b = c\"}" "a + b = c"} This can also be written with an antiquotation: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"} Attempting to obtain the certified term for - @{ML_response_fake_both [display,gray] + @{ML_matchresult_fake_both [display,gray] "@{cterm \"1 + True\"}" "Type unification failed \"} yields an error (since the term is not typable). A slightly more elaborate example that type-checks is: -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val natT = @{typ \"nat\"} val zero = @{term \"0::nat\"} @@ -1465,13 +1465,13 @@ you obtain the certified type for the Isabelle type @{typ "nat \ bool"} on the ML-level as follows: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Thm.ctyp_of @{context} (@{typ nat} --> @{typ bool})" "nat \ bool"} or with the antiquotation: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{ctyp \"nat \ bool\"}" "nat \ bool"} @@ -1479,14 +1479,14 @@ pattern-match against them. However, we can construct them. For example the function @{ML_ind apply in Thm} produces a certified application. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Thm.apply @{cterm \"P::nat \ bool\"} @{cterm \"3::nat\"}" "P 3"} - Similarly the function @{ML_ind list_comb in Drule} from the structure @{ML_struct Drule} + Similarly the function @{ML_ind list_comb in Drule} from the structure @{ML_structure Drule} applies a list of @{ML_type cterm}s. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val chead = @{cterm \"P::unit \ nat \ bool\"} val cargs = [@{cterm \"()\"}, @{cterm \"3::nat\"}] @@ -1546,7 +1546,7 @@ If we print out the value of @{ML my_thm} then we see only the final statement of the theorem. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "pwriteln (pretty_thm @{context} my_thm)" "\\x. P x \ Q x; P t\ \ Q t"} @@ -1570,7 +1570,7 @@ yet stored in Isabelle's theorem database. Consequently, it cannot be referenced on the user level. One way to store it in the theorem database is by using the function @{ML_ind note in Local_Theory} from the structure - @{ML_struct Local_Theory} (the Isabelle command + @{ML_structure Local_Theory} (the Isabelle command \isacommand{local\_setup} will be explained in more detail in Section~\ref{sec:local}). \ @@ -1606,13 +1606,13 @@ Note that we have to use another name under which the theorem is stored, since Isabelle does not allow us to call @{ML_ind note in Local_Theory} twice with the same name. The attribute needs to be wrapped inside the function @{ML_ind - internal in Attrib} from the structure @{ML_struct Attrib}. If we use the function + internal in Attrib} from the structure @{ML_structure Attrib}. If we use the function @{ML get_thm_names_from_ss} from the previous chapter, we can check whether the theorem has actually been added. - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "let fun pred s = match_string \"my_thm_simp\" s in @@ -1716,7 +1716,7 @@ text \ Testing them for alpha equality produces: - @{ML_response [display,gray] + @{ML_matchresult [display,gray] "(Thm.eq_thm_prop (@{thm thm1}, @{thm thm2}), Thm.eq_thm_prop (@{thm thm2}, @{thm thm3}))" "(true, false)"} @@ -1725,7 +1725,7 @@ the functions @{ML_ind lhs_of in Thm} and @{ML_ind rhs_of in Thm} return the left and right-hand side, respectively, of a meta-equality. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val eq = @{thm True_def} in @@ -1745,7 +1745,7 @@ text \ We can destruct them into premises and conclusions as follows. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val ctxt = @{context} fun prems_and_concl thm = @@ -1778,7 +1778,7 @@ this, we build the theorem @{term "True \ True"} (Line 1) and then unfold the constant @{term "True"} according to its definition (Line 2). - @{ML_response_fake [display,gray,linenos] + @{ML_matchresult_fake [display,gray,linenos] "Thm.reflexive @{cterm \"True\"} |> Simplifier.rewrite_rule @{context} [@{thm True_def}] |> pretty_thm @{context} @@ -1795,14 +1795,14 @@ @{ML_ind rulify in Object_Logic} replaces all object connectives by equivalents in the meta logic. For example - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Object_Logic.rulify @{context} @{thm foo_test2}" "\?A; ?B\ \ ?C"} The transformation in the other direction can be achieved with function @{ML_ind atomize in Object_Logic} and the following code. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val thm = @{thm foo_test1} val meta_eq = Object_Logic.atomize @{context} (Thm.cprop_of thm) @@ -1837,16 +1837,16 @@ text \ This function produces for the theorem @{thm [source] list.induct} - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "atomize_thm @{context} @{thm list.induct}" "\P list. P [] \ (\a list. P list \ P (a # list)) \ P list"} Theorems can also be produced from terms by giving an explicit proof. One way to achieve this is by using the function @{ML_ind prove in Goal} - in the structure @{ML_struct Goal}. For example below we use this function + in the structure @{ML_structure Goal}. For example below we use this function to prove the term @{term "P \ P"}. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val trm = @{term \"P \ P::bool\"} val tac = K (assume_tac @{context} 1) @@ -1878,7 +1878,7 @@ With them we can now produce three theorem instances of the proposition. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "multi_test @{context} 3" "[\"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\"]"} @@ -1898,12 +1898,12 @@ text \ While the LCF-approach of going through interfaces ensures soundness in Isabelle, there is the function @{ML_ind make_thm in Skip_Proof} in the structure - @{ML_struct Skip_Proof} that allows us to turn any proposition into a theorem. + @{ML_structure Skip_Proof} that allows us to turn any proposition into a theorem. Potentially making the system unsound. This is sometimes useful for developing purposes, or when explicit proof construction should be omitted due to performace reasons. An example of this function is as follows: - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "Skip_Proof.make_thm @{theory} @{prop \"True = False\"}" "True = False"} @@ -1926,14 +1926,14 @@ The auxiliary data of this lemma can be retrieved using the function @{ML_ind get_tags in Thm}. So far the the auxiliary data of this lemma is - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Thm.get_tags @{thm foo_data}" "[(\"name\", \"General.foo_data\"), (\"kind\", \"lemma\")]"} consisting of a name and a kind. When we store lemmas in the theorem database, we might want to explicitly extend this data by attaching case names to the two premises of the lemma. This can be done with the function @{ML_ind name in Rule_Cases} - from the structure @{ML_struct Rule_Cases}. + from the structure @{ML_structure Rule_Cases}. \ local_setup %gray \ @@ -1944,7 +1944,7 @@ text \ The data of the theorem @{thm [source] foo_data'} is then as follows: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Thm.get_tags @{thm foo_data'}" "[(\"name\", \"General.foo_data'\"), (\"kind\", \"lemma\"), (\"case_names\", \"foo_case_one;foo_case_two\")]"} @@ -1996,7 +1996,7 @@ proving a theorem, especially when the proof is by \auto\. These theorems can be obtained by introspecting the proved theorem. To introspect a theorem, let us define the following three functions that analyse the @{ML_type_ind proof_body} data-structure from the - structure @{ML_struct Proofterm}. + structure @{ML_structure Proofterm}. \ ML %grayML\fun pthms_of (PBody {thms, ...}) = map #2 thms @@ -2036,7 +2036,7 @@ extracting this information. Let us first extract the name of the established theorem. This can be done with - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{thm my_conjIa} |> Thm.proof_body_of |> get_names" @@ -2050,7 +2050,7 @@ and @{thm [source] conjunct2}. We can obtain them by descending into the first level of the proof-tree, as follows. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{thm my_conjIa} |> Thm.proof_body_of |> get_pbodies @@ -2064,7 +2064,7 @@ proof in Isabelle. Note also that applications of \assumption\ do not count as a separate theorem, as you can see in the following code. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{thm my_conjIb} |> Thm.proof_body_of |> get_pbodies @@ -2077,7 +2077,7 @@ and @{thm [source] my_conjIb}, as can be seen by the theorems that are returned for @{thm [source] my_conjIc}. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "@{thm my_conjIc} |> Thm.proof_body_of |> get_pbodies @@ -2092,7 +2092,7 @@ means we obtain the theorems that are used in order to prove @{thm [source] conjunct1}, @{thm [source] conjunct2} and @{thm [source] conjI}. - @{ML_response_fake [display, gray] + @{ML_matchresult_fake [display, gray] "@{thm my_conjIa} |> Thm.proof_body_of |> get_pbodies @@ -2408,7 +2408,7 @@ text \ then you can see it is added to the initially empty list. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "MyThms.get @{context}" "[\"True\"]"} @@ -2422,7 +2422,7 @@ not need to be explicitly given. These three declarations will cause the theorem list to be updated as: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "MyThms.get @{context}" "[\"True\", \"Suc (Suc 0) = 2\"]"} @@ -2435,7 +2435,7 @@ text \After this, the theorem list is again: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "MyThms.get @{context}" "[\"True\"]"} @@ -2468,7 +2468,7 @@ The function @{ML str in Pretty} transforms a (plain) string into such a pretty type. For example - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "Pretty.str \"test\"" "String (\"test\", 4)"} where the result indicates that we transformed a string with length 4. Once @@ -2503,7 +2503,7 @@ If we print out the string using the usual ``quick-and-dirty'' method, then we obtain the ugly output: -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "tracing test_str" "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar foooooooooo ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa @@ -2512,7 +2512,7 @@ We obtain the same if we just use the function @{ML pprint}. -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "pprint (Pretty.str test_str)" "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar foooooooooo ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa @@ -2526,7 +2526,7 @@ list. To print this list of pretty types as a single string, we concatenate them with the function @{ML_ind blk in Pretty} as follows: -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs = map Pretty.str (space_explode \" \" test_str) in @@ -2542,7 +2542,7 @@ indentation of the printed string. You can increase the indentation and obtain -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs = map Pretty.str (space_explode \" \" test_str) in @@ -2557,7 +2557,7 @@ that every line starts with the same indent, you can use the function @{ML_ind indent in Pretty} as follows: -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs = map Pretty.str (space_explode \" \" test_str) in @@ -2572,7 +2572,7 @@ have the linebreaks handled properly, you can use the function @{ML_ind commas in Pretty}. For example -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs = map (Pretty.str o string_of_int) (99998 upto 100020) in @@ -2590,7 +2590,7 @@ text \ -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs = map (Pretty.str o string_of_int) (99998 upto 100020) in @@ -2629,7 +2629,7 @@ can occur. We do the same after the @{text [quotes] "and"}. This gives you for example -@{ML_response_fake [display,gray] +@{ML_matchresult_fake [display,gray] "let val ptrs1 = map (Pretty.str o string_of_int) (1 upto 22) val ptrs2 = map (Pretty.str o string_of_int) (10 upto 28) @@ -2646,7 +2646,7 @@ a list of items, but automatically inserts forced breaks between each item. Compare - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val a_and_b = [Pretty.str \"a\", Pretty.str \"b\"] in @@ -2661,7 +2661,7 @@ It is used for example in the command \isacommand{print\_theorems}. An example is as follows. - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "let val pstrs = map (Pretty.str o string_of_int) (4 upto 10) in @@ -2681,7 +2681,7 @@ out the the terms produced by the the function @{ML de_bruijn} from exercise~\ref{ex:debruijn} we obtain the following: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "pprint (Syntax.pretty_term @{context} (de_bruijn 4))" "(P 3 = P 4 \ P 4 \ P 3 \ P 2 \ P 1) \ (P 2 = P 3 \ P 4 \ P 3 \ P 2 \ P 1) \ @@ -2715,14 +2715,14 @@ line break, because we do not want that a line break occurs there. Now you can write - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "tell_type @{context} @{term \"min (Suc 0)\"}" "The term \"min (Suc 0)\" has type \"nat \ nat\"."} To see the proper line breaking, you can try out the function on a bigger term and type. For example: - @{ML_response_fake [display,gray] + @{ML_matchresult_fake [display,gray] "tell_type @{context} @{term \"(=) ((=) ((=) ((=) ((=) (=)))))\"}" "The term \"(=) ((=) ((=) ((=) ((=) (=)))))\" has type \"((((('a \ 'a \ bool) \ bool) \ bool) \ bool) \ bool) \ bool\"."}