251 pp_constr "Type" (pp_pair (pp_qstr a, pp_list (map raw_pp_typ tys))) |
251 pp_constr "Type" (pp_pair (pp_qstr a, pp_list (map raw_pp_typ tys))) |
252 end*} |
252 end*} |
253 |
253 |
254 text {* |
254 text {* |
255 We can install this pretty printer with the function |
255 We can install this pretty printer with the function |
256 @{ML_ind addPrettyPrinter in PolyML} as follows. |
256 @{ML_ind ML_system_pp} as follows. |
257 *} |
257 *} |
258 |
258 |
259 ML %grayML{*PolyML.addPrettyPrinter |
259 ML %grayML{*ML_system_pp |
260 (fn _ => fn _ => ml_pretty o Pretty.to_ML o raw_pp_typ)*} |
260 (fn _ => fn _ => Pretty.to_polyml o raw_pp_typ)*} |
261 |
261 |
|
262 ML \<open>@{typ "bool"}\<close> |
262 text {* |
263 text {* |
263 Now the type bool is printed out in full detail. |
264 Now the type bool is printed out in full detail. |
264 |
265 |
265 @{ML_response [display,gray] |
266 @{ML_response [display,gray] |
266 "@{typ \"bool\"}" |
267 "@{typ \"bool\"}" |
1078 @{ML_response [display, gray] |
1079 @{ML_response [display, gray] |
1079 "let |
1080 "let |
1080 val trm_list = |
1081 val trm_list = |
1081 [@{term_pat \"?X\"}, @{term_pat \"a\"}, |
1082 [@{term_pat \"?X\"}, @{term_pat \"a\"}, |
1082 @{term_pat \"f (\<lambda>a b. ?X a b) c\"}, |
1083 @{term_pat \"f (\<lambda>a b. ?X a b) c\"}, |
1083 @{term_pat \"\<lambda>a b. (op +) a b\"}, |
1084 @{term_pat \"\<lambda>a b. (+) a b\"}, |
1084 @{term_pat \"\<lambda>a. (op +) a ?Y\"}, @{term_pat \"?X ?Y\"}, |
1085 @{term_pat \"\<lambda>a. (+) a ?Y\"}, @{term_pat \"?X ?Y\"}, |
1085 @{term_pat \"\<lambda>a b. ?X a b ?Y\"}, @{term_pat \"\<lambda>a. ?X a a\"}, |
1086 @{term_pat \"\<lambda>a b. ?X a b ?Y\"}, @{term_pat \"\<lambda>a. ?X a a\"}, |
1086 @{term_pat \"?X a\"}] |
1087 @{term_pat \"?X a\"}] |
1087 in |
1088 in |
1088 map Pattern.pattern trm_list |
1089 map Pattern.pattern trm_list |
1089 end" |
1090 end" |
1104 @{ML_response_fake [display, gray] |
1105 @{ML_response_fake [display, gray] |
1105 "let |
1106 "let |
1106 val trm1 = @{term_pat \"\<lambda>x y. g (?X y x) (f (?Y x))\"} |
1107 val trm1 = @{term_pat \"\<lambda>x y. g (?X y x) (f (?Y x))\"} |
1107 val trm2 = @{term_pat \"\<lambda>u v. g u (f u)\"} |
1108 val trm2 = @{term_pat \"\<lambda>u v. g u (f u)\"} |
1108 val init = Envir.empty 0 |
1109 val init = Envir.empty 0 |
1109 val env = Pattern.unify @{theory} (trm1, trm2) init |
1110 val env = Pattern.unify (Context.Proof @{context}) (trm1, trm2) init (* FIXME: Reference to generic context *) |
1110 in |
1111 in |
1111 pretty_env @{context} (Envir.term_env env) |
1112 pretty_env @{context} (Envir.term_env env) |
1112 end" |
1113 end" |
1113 "[?X := \<lambda>y x. x, ?Y := \<lambda>x. x]"} |
1114 "[?X := \<lambda>y x. x, ?Y := \<lambda>x. x]"} |
1114 |
1115 |
1213 behaviour since the unification has more than one solution. One way round |
1214 behaviour since the unification has more than one solution. One way round |
1214 this problem is to instantiate the schematic variables @{text "?P"} and |
1215 this problem is to instantiate the schematic variables @{text "?P"} and |
1215 @{text "?x"}. Instantiation function for theorems is |
1216 @{text "?x"}. Instantiation function for theorems is |
1216 @{ML_ind instantiate_normalize in Drule} from the structure |
1217 @{ML_ind instantiate_normalize in Drule} from the structure |
1217 @{ML_struct Drule}. One problem, however, is |
1218 @{ML_struct Drule}. One problem, however, is |
1218 that this function expects the instantiations as lists of @{ML_type ctyp} |
1219 that this function expects the instantiations as lists of @{ML_type "((indexname * sort) * ctyp)"} |
1219 and @{ML_type cterm} pairs: |
1220 respective @{ML_type "(indexname * typ) * cterm"}: |
1220 |
1221 |
1221 \begin{isabelle} |
1222 \begin{isabelle} |
1222 @{ML instantiate_normalize in Drule}@{text ":"} |
1223 @{ML instantiate_normalize in Drule}@{text ":"} |
1223 @{ML_type "(ctyp * ctyp) list * (cterm * cterm) list -> thm -> thm"} |
1224 @{ML_type "((indexname * sort) * ctyp) list * ((indexname * typ) * cterm) list -> thm -> thm"} |
1224 \end{isabelle} |
1225 \end{isabelle} |
1225 |
1226 |
1226 This means we have to transform the environment the higher-order matching |
1227 This means we have to transform the environment the higher-order matching |
1227 function returns into such an instantiation. For this we use the functions |
1228 function returns into such an instantiation. For this we use the functions |
1228 @{ML_ind term_env in Envir} and @{ML_ind type_env in Envir}, which extract |
1229 @{ML_ind term_env in Envir} and @{ML_ind type_env in Envir}, which extract |
1229 from an environment the corresponding variable mappings for schematic type |
1230 from an environment the corresponding variable mappings for schematic type |
1230 and term variables. These mappings can be turned into proper |
1231 and term variables. These mappings can be turned into proper |
1231 @{ML_type ctyp}-pairs with the function |
1232 @{ML_type ctyp}-pairs with the function |
1232 *} |
1233 *} |
1233 |
1234 |
1234 ML %grayML{*fun prep_trm thy (x, (T, t)) = |
1235 ML %grayML{*fun prep_trm ctxt (x, (T, t)) = |
1235 (cterm_of thy (Var (x, T)), cterm_of thy t)*} |
1236 ((x, T), Thm.cterm_of ctxt t)*} |
1236 |
1237 |
1237 text {* |
1238 text {* |
1238 and into proper @{ML_type cterm}-pairs with |
1239 and into proper @{ML_type cterm}-pairs with |
1239 *} |
1240 *} |
1240 |
1241 |
1241 ML %grayML{*fun prep_ty thy (x, (S, ty)) = |
1242 ML %grayML{*fun prep_ty ctxt (x, (S, ty)) = |
1242 (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)*} |
1243 ((x, S), Thm.ctyp_of ctxt ty)*} |
1243 |
1244 |
1244 text {* |
1245 text {* |
1245 We can now calculate the instantiations from the matching function. |
1246 We can now calculate the instantiations from the matching function. |
1246 *} |
1247 *} |
1247 |
1248 |
1248 ML %linenosgray{*fun matcher_inst thy pat trm i = |
1249 ML %linenosgray{*fun matcher_inst ctxt pat trm i = |
1249 let |
1250 let |
1250 val univ = Unify.matchers thy [(pat, trm)] |
1251 val univ = Unify.matchers (Context.Proof ctxt) [(pat, trm)] |
1251 val env = nth (Seq.list_of univ) i |
1252 val env = nth (Seq.list_of univ) i |
1252 val tenv = Vartab.dest (Envir.term_env env) |
1253 val tenv = Vartab.dest (Envir.term_env env) |
1253 val tyenv = Vartab.dest (Envir.type_env env) |
1254 val tyenv = Vartab.dest (Envir.type_env env) |
1254 in |
1255 in |
1255 (map (prep_ty thy) tyenv, map (prep_trm thy) tenv) |
1256 (map (prep_ty ctxt) tyenv, map (prep_trm ctxt) tenv) |
1256 end*} |
1257 end*} |
1257 |
1258 |
|
1259 ML \<open>Context.get_generic_context\<close> |
1258 text {* |
1260 text {* |
1259 In Line 3 we obtain the higher-order matcher. We assume there is a finite |
1261 In Line 3 we obtain the higher-order matcher. We assume there is a finite |
1260 number of them and select the one we are interested in via the parameter |
1262 number of them and select the one we are interested in via the parameter |
1261 @{text i} in the next line. In Lines 5 and 6 we destruct the resulting |
1263 @{text i} in the next line. In Lines 5 and 6 we destruct the resulting |
1262 environments using the function @{ML_ind dest in Vartab}. Finally, we need |
1264 environments using the function @{ML_ind dest in Vartab}. Finally, we need |
1427 converts a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} |
1429 converts a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} |
1428 term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are |
1430 term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are |
1429 abstract objects that are guaranteed to be type-correct, and they can only |
1431 abstract objects that are guaranteed to be type-correct, and they can only |
1430 be constructed via ``official interfaces''. |
1432 be constructed via ``official interfaces''. |
1431 |
1433 |
1432 Certification is always relative to a theory context. For example you can |
1434 Certification is always relative to a context. For example you can |
1433 write: |
1435 write: |
1434 |
1436 |
1435 @{ML_response_fake [display,gray] |
1437 @{ML_response_fake [display,gray] |
1436 "cterm_of @{theory} @{term \"(a::nat) + b = c\"}" |
1438 "Thm.cterm_of @{context} @{term \"(a::nat) + b = c\"}" |
1437 "a + b = c"} |
1439 "a + b = c"} |
1438 |
1440 |
1439 This can also be written with an antiquotation: |
1441 This can also be written with an antiquotation: |
1440 |
1442 |
1441 @{ML_response_fake [display,gray] |
1443 @{ML_response_fake [display,gray] |
1455 "let |
1457 "let |
1456 val natT = @{typ \"nat\"} |
1458 val natT = @{typ \"nat\"} |
1457 val zero = @{term \"0::nat\"} |
1459 val zero = @{term \"0::nat\"} |
1458 val plus = Const (@{const_name plus}, [natT, natT] ---> natT) |
1460 val plus = Const (@{const_name plus}, [natT, natT] ---> natT) |
1459 in |
1461 in |
1460 cterm_of @{theory} (plus $ zero $ zero) |
1462 Thm.cterm_of @{context} (plus $ zero $ zero) |
1461 end" |
1463 end" |
1462 "0 + 0"} |
1464 "0 + 0"} |
1463 |
1465 |
1464 In Isabelle not just terms need to be certified, but also types. For example, |
1466 In Isabelle not just terms need to be certified, but also types. For example, |
1465 you obtain the certified type for the Isabelle type @{typ "nat \<Rightarrow> bool"} on |
1467 you obtain the certified type for the Isabelle type @{typ "nat \<Rightarrow> bool"} on |
1466 the ML-level as follows: |
1468 the ML-level as follows: |
1467 |
1469 |
1468 @{ML_response_fake [display,gray] |
1470 @{ML_response_fake [display,gray] |
1469 "ctyp_of @{theory} (@{typ nat} --> @{typ bool})" |
1471 "Thm.ctyp_of @{context} (@{typ nat} --> @{typ bool})" |
1470 "nat \<Rightarrow> bool"} |
1472 "nat \<Rightarrow> bool"} |
1471 |
1473 |
1472 or with the antiquotation: |
1474 or with the antiquotation: |
1473 |
1475 |
1474 @{ML_response_fake [display,gray] |
1476 @{ML_response_fake [display,gray] |
1573 @{ML_struct Local_Theory} (the Isabelle command |
1575 @{ML_struct Local_Theory} (the Isabelle command |
1574 \isacommand{local\_setup} will be explained in more detail in |
1576 \isacommand{local\_setup} will be explained in more detail in |
1575 Section~\ref{sec:local}). |
1577 Section~\ref{sec:local}). |
1576 *} |
1578 *} |
1577 |
1579 |
|
1580 (*FIXME: add forward reference to Proof_Context.export *) |
|
1581 ML %linenosgray{*val my_thm_vars = |
|
1582 let |
|
1583 val ctxt0 = @{context} |
|
1584 val (_, ctxt1) = Variable.add_fixes ["P", "Q", "t"] ctxt0 |
|
1585 in |
|
1586 singleton (Proof_Context.export ctxt1 ctxt0) my_thm |
|
1587 end*} |
|
1588 |
1578 local_setup %gray {* |
1589 local_setup %gray {* |
1579 Local_Theory.note ((@{binding "my_thm"}, []), [my_thm]) #> snd *} |
1590 Local_Theory.note ((@{binding "my_thm"}, []), [my_thm_vars]) #> snd *} |
|
1591 |
1580 |
1592 |
1581 text {* |
1593 text {* |
1582 The third argument of @{ML note in Local_Theory} is the list of theorems we |
1594 The third argument of @{ML note in Local_Theory} is the list of theorems we |
1583 want to store under a name. We can store more than one under a single name. |
1595 want to store under a name. We can store more than one under a single name. |
1584 The first argument of @{ML note in Local_Theory} is the name under |
1596 The first argument of @{ML note in Local_Theory} is the name under |
1588 @{ML_ind simp_add in Simplifier}, for adding the theorem to the simpset: |
1600 @{ML_ind simp_add in Simplifier}, for adding the theorem to the simpset: |
1589 *} |
1601 *} |
1590 |
1602 |
1591 local_setup %gray {* |
1603 local_setup %gray {* |
1592 Local_Theory.note ((@{binding "my_thm_simp"}, |
1604 Local_Theory.note ((@{binding "my_thm_simp"}, |
1593 [Attrib.internal (K Simplifier.simp_add)]), [my_thm]) #> snd *} |
1605 [Attrib.internal (K Simplifier.simp_add)]), [my_thm_vars]) #> snd *} |
1594 |
1606 |
1595 text {* |
1607 text {* |
1596 Note that we have to use another name under which the theorem is stored, |
1608 Note that we have to use another name under which the theorem is stored, |
1597 since Isabelle does not allow us to call @{ML_ind note in Local_Theory} twice |
1609 since Isabelle does not allow us to call @{ML_ind note in Local_Theory} twice |
1598 with the same name. The attribute needs to be wrapped inside the function @{ML_ind |
1610 with the same name. The attribute needs to be wrapped inside the function @{ML_ind |
1718 @{ML_response_fake [display,gray] |
1730 @{ML_response_fake [display,gray] |
1719 "let |
1731 "let |
1720 val eq = @{thm True_def} |
1732 val eq = @{thm True_def} |
1721 in |
1733 in |
1722 (Thm.lhs_of eq, Thm.rhs_of eq) |
1734 (Thm.lhs_of eq, Thm.rhs_of eq) |
1723 |> pairself (Pretty.string_of o (pretty_cterm @{context})) |
1735 |> apply2 (Pretty.string_of o (pretty_cterm @{context})) |
1724 end" |
1736 end" |
1725 "(True, (\<lambda>x. x) = (\<lambda>x. x))"} |
1737 "(True, (\<lambda>x. x) = (\<lambda>x. x))"} |
1726 |
1738 |
1727 Other function produce terms that can be pattern-matched. |
1739 Other function produce terms that can be pattern-matched. |
1728 Suppose the following two theorems. |
1740 Suppose the following two theorems. |
1851 proved. The fifth is a corresponding proof given in form of a tactic (we explain |
1863 proved. The fifth is a corresponding proof given in form of a tactic (we explain |
1852 tactics in Chapter~\ref{chp:tactical}). In the code above, the tactic proves the |
1864 tactics in Chapter~\ref{chp:tactical}). In the code above, the tactic proves the |
1853 theorem by assumption. |
1865 theorem by assumption. |
1854 |
1866 |
1855 There is also the possibility of proving multiple goals at the same time |
1867 There is also the possibility of proving multiple goals at the same time |
1856 using the function @{ML_ind prove_multi in Goal}. For this let us define the |
1868 using the function @{ML_ind prove_common in Goal}. For this let us define the |
1857 following three helper functions. |
1869 following three helper functions. |
1858 *} |
1870 *} |
1859 |
1871 |
1860 ML %grayML{*fun rep_goals i = replicate i @{prop "f x = f x"} |
1872 ML %grayML{*fun rep_goals i = replicate i @{prop "f x = f x"} |
1861 fun rep_tacs i = replicate i (rtac @{thm refl}) |
1873 fun rep_tacs i = replicate i (resolve_tac @{context} [@{thm refl}]) |
1862 |
1874 |
1863 fun multi_test ctxt i = |
1875 fun multi_test ctxt i = |
1864 Goal.prove_multi ctxt ["f", "x"] [] (rep_goals i) |
1876 Goal.prove_common ctxt NONE ["f", "x"] [] (rep_goals i) |
1865 (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*} |
1877 (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*} |
1866 |
1878 |
1867 text {* |
1879 text {* |
1868 With them we can now produce three theorem instances of the |
1880 With them we can now produce three theorem instances of the |
1869 proposition. |
1881 proposition. |
1870 |
1882 |
1871 @{ML_response_fake [display, gray] |
1883 @{ML_response_fake [display, gray] |
1872 "multi_test @{context} 3" |
1884 "multi_test @{context} 3" |
1873 "[\"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\"]"} |
1885 "[\"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\", \"?f ?x = ?f ?x\"]"} |
1874 |
1886 |
1875 However you should be careful with @{ML prove_multi in Goal} and very |
1887 However you should be careful with @{ML prove_common in Goal} and very |
1876 large goals. If you increase the counter in the code above to @{text 3000}, |
1888 large goals. If you increase the counter in the code above to @{text 3000}, |
1877 you will notice that takes approximately ten(!) times longer than |
1889 you will notice that takes approximately ten(!) times longer than |
1878 using @{ML map} and @{ML prove in Goal}. |
1890 using @{ML map} and @{ML prove in Goal}. |
1879 *} |
1891 *} |
1880 |
1892 |
1881 ML %grayML{*let |
1893 ML %grayML{*let |
1882 fun test_prove ctxt thm = |
1894 fun test_prove ctxt thm = |
1883 Goal.prove ctxt ["P", "x"] [] thm (K (rtac @{thm refl} 1)) |
1895 Goal.prove ctxt ["P", "x"] [] thm (K (resolve_tac @{context} [@{thm refl}] 1)) |
1884 in |
1896 in |
1885 map (test_prove @{context}) (rep_goals 3000) |
1897 map (test_prove @{context}) (rep_goals 3000) |
1886 end*} |
1898 end*} |
1887 |
1899 |
1888 text {* |
1900 text {* |
2713 |
2725 |
2714 To see the proper line breaking, you can try out the function on a bigger term |
2726 To see the proper line breaking, you can try out the function on a bigger term |
2715 and type. For example: |
2727 and type. For example: |
2716 |
2728 |
2717 @{ML_response_fake [display,gray] |
2729 @{ML_response_fake [display,gray] |
2718 "tell_type @{context} @{term \"op = (op = (op = (op = (op = op =))))\"}" |
2730 "tell_type @{context} @{term \"(=) ((=) ((=) ((=) ((=) (=)))))\"}" |
2719 "The term \"op = (op = (op = (op = (op = op =))))\" has type |
2731 "The term \"(=) ((=) ((=) ((=) ((=) (=)))))\" has type |
2720 \"((((('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool\"."} |
2732 \"((((('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool) \<Rightarrow> bool\"."} |
2721 |
2733 |
2722 \begin{readmore} |
2734 \begin{readmore} |
2723 The general infrastructure for pretty-printing is implemented in the file |
2735 The general infrastructure for pretty-printing is implemented in the file |
2724 @{ML_file "Pure/General/pretty.ML"}. The file @{ML_file "Pure/Syntax/syntax.ML"} |
2736 @{ML_file "Pure/General/pretty.ML"}. The file @{ML_file "Pure/Syntax/syntax.ML"} |