ProgTutorial/Essential.thy
changeset 562 daf404920ab9
parent 559 ffa5c4ec9611
child 565 cecd7a941885
equal deleted inserted replaced
561:aec7073d4645 562:daf404920ab9
   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\"}"
   284 
   285 
   285   We can restore the usual behaviour of Isabelle's pretty printer
   286   We can restore the usual behaviour of Isabelle's pretty printer
   286   with the code
   287   with the code
   287 *}
   288 *}
   288 
   289 
   289 ML %grayML{*PolyML.addPrettyPrinter 
   290 ML %grayML{*ML_system_pp
   290   (fn _ => fn _ => ml_pretty o Pretty.to_ML o Proof_Display.pp_typ Pure.thy)*}
   291   (fn depth => fn _ => ML_Pretty.to_polyml o Pretty.to_ML depth o Proof_Display.pp_typ Theory.get_pure)*}
   291 
   292 
   292 text {*
   293 text {*
   293   After that the types for booleans, lists and so on are printed out again 
   294   After that the types for booleans, lists and so on are printed out again 
   294   the standard Isabelle way.
   295   the standard Isabelle way.
   295 
   296 
   815       |> pwriteln
   816       |> pwriteln
   816 
   817 
   817 fun pretty_tyenv ctxt tyenv =
   818 fun pretty_tyenv ctxt tyenv =
   818 let
   819 let
   819   fun get_typs (v, (s, T)) = (TVar (v, s), T)
   820   fun get_typs (v, (s, T)) = (TVar (v, s), T)
   820   val print = pairself (pretty_typ ctxt)
   821   val print = apply2 (pretty_typ ctxt)
   821 in 
   822 in 
   822   pretty_helper (print o get_typs) tyenv
   823   pretty_helper (print o get_typs) tyenv
   823 end*}
   824 end*}
   824 text_raw {*
   825 text_raw {*
   825   \end{isabelle}
   826   \end{isabelle}
   995 *}
   996 *}
   996 
   997 
   997 ML %grayML{*fun pretty_env ctxt env =
   998 ML %grayML{*fun pretty_env ctxt env =
   998 let
   999 let
   999   fun get_trms (v, (T, t)) = (Var (v, T), t) 
  1000   fun get_trms (v, (T, t)) = (Var (v, T), t) 
  1000   val print = pairself (pretty_term ctxt)
  1001   val print = apply2 (pretty_term ctxt)
  1001 in
  1002 in
  1002   pretty_helper (print o get_trms) env 
  1003   pretty_helper (print o get_trms) env 
  1003 end*}
  1004 end*}
  1004 
  1005 
  1005 text {*
  1006 text {*
  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 
  1132 let 
  1133 let 
  1133   val trm1 = @{term_pat "?X ?Y"}
  1134   val trm1 = @{term_pat "?X ?Y"}
  1134   val trm2 = @{term "f a"}
  1135   val trm2 = @{term "f a"}
  1135   val init = Envir.empty 0
  1136   val init = Envir.empty 0
  1136 in
  1137 in
  1137   Unify.unifiers (@{theory}, init, [(trm1, trm2)])
  1138   Unify.unifiers (Context.Proof @{context}, init, [(trm1, trm2)])
  1138 end *}
  1139 end *}
  1139 
  1140 
  1140 text {*
  1141 text {*
  1141   The unifiers can be extracted from the lazy sequence using the 
  1142   The unifiers can be extracted from the lazy sequence using the 
  1142   function @{ML_ind "Seq.pull"}. In the example we obtain three 
  1143   function @{ML_ind "Seq.pull"}. In the example we obtain three 
  1169 "let 
  1170 "let 
  1170   val trm1 = @{term \"a\"}
  1171   val trm1 = @{term \"a\"}
  1171   val trm2 = @{term \"b\"}
  1172   val trm2 = @{term \"b\"}
  1172   val init = Envir.empty 0
  1173   val init = Envir.empty 0
  1173 in
  1174 in
  1174   Unify.unifiers (@{theory}, init, [(trm1, trm2)])
  1175   Unify.unifiers (Context.Proof @{context}, init, [(trm1, trm2)])
  1175   |> Seq.pull
  1176   |> Seq.pull
  1176 end"
  1177 end"
  1177 "NONE"}
  1178 "NONE"}
  1178 
  1179 
  1179   In order to find a reasonable solution for a unification problem, Isabelle
  1180   In order to find a reasonable solution for a unification problem, Isabelle
  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 
  1266   @{term "Q True"}. 
  1268   @{term "Q True"}. 
  1267  
  1269  
  1268 
  1270 
  1269   @{ML_response_fake [gray,display,linenos] 
  1271   @{ML_response_fake [gray,display,linenos] 
  1270   "let  
  1272   "let  
  1271   val pat = Logic.strip_imp_concl (prop_of @{thm spec})
  1273   val pat = Logic.strip_imp_concl (Thm.prop_of @{thm spec})
  1272   val trm = @{term \"Trueprop (Q True)\"}
  1274   val trm = @{term \"Trueprop (Q True)\"}
  1273   val inst = matcher_inst @{theory} pat trm 1
  1275   val inst = matcher_inst @{context} pat trm 1
  1274 in
  1276 in
  1275   Drule.instantiate_normalize inst @{thm spec}
  1277   Drule.instantiate_normalize inst @{thm spec}
  1276 end"
  1278 end"
  1277   "\<forall>x. Q x \<Longrightarrow> Q True"}
  1279   "\<forall>x. Q x \<Longrightarrow> Q True"}
  1278 
  1280 
  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.
  1793   @{ML_ind atomize in Object_Logic} and the following code.
  1805   @{ML_ind atomize in Object_Logic} and the following code.
  1794 
  1806 
  1795   @{ML_response_fake [display,gray]
  1807   @{ML_response_fake [display,gray]
  1796   "let
  1808   "let
  1797   val thm = @{thm foo_test1}
  1809   val thm = @{thm foo_test1}
  1798   val meta_eq = Object_Logic.atomize @{context} (cprop_of thm)
  1810   val meta_eq = Object_Logic.atomize @{context} (Thm.cprop_of thm)
  1799 in
  1811 in
  1800   Raw_Simplifier.rewrite_rule @{context} [meta_eq] thm
  1812   Raw_Simplifier.rewrite_rule @{context} [meta_eq] thm
  1801 end"
  1813 end"
  1802   "?A \<longrightarrow> ?B \<longrightarrow> ?C"}
  1814   "?A \<longrightarrow> ?B \<longrightarrow> ?C"}
  1803 
  1815 
  1817 *}
  1829 *}
  1818 
  1830 
  1819 ML %grayML{*fun atomize_thm ctxt thm =
  1831 ML %grayML{*fun atomize_thm ctxt thm =
  1820 let
  1832 let
  1821   val thm' = forall_intr_vars thm
  1833   val thm' = forall_intr_vars thm
  1822   val thm'' = Object_Logic.atomize ctxt (cprop_of thm')
  1834   val thm'' = Object_Logic.atomize ctxt (Thm.cprop_of thm')
  1823 in
  1835 in
  1824   Raw_Simplifier.rewrite_rule ctxt [thm''] thm'
  1836   Raw_Simplifier.rewrite_rule ctxt [thm''] thm'
  1825 end*}
  1837 end*}
  1826 
  1838 
  1827 text {*
  1839 text {*
  1837   to prove the term @{term "P \<Longrightarrow> P"}.
  1849   to prove the term @{term "P \<Longrightarrow> P"}.
  1838   
  1850   
  1839   @{ML_response_fake [display,gray]
  1851   @{ML_response_fake [display,gray]
  1840   "let
  1852   "let
  1841   val trm = @{term \"P \<Longrightarrow> P::bool\"}
  1853   val trm = @{term \"P \<Longrightarrow> P::bool\"}
  1842   val tac = K (atac 1)
  1854   val tac = K (assume_tac @{context} 1)
  1843 in
  1855 in
  1844   Goal.prove @{context} [\"P\"] [] trm tac
  1856   Goal.prove @{context} [\"P\"] [] trm tac
  1845 end"
  1857 end"
  1846   "?P \<Longrightarrow> ?P"}
  1858   "?P \<Longrightarrow> ?P"}
  1847 
  1859 
  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 {*
  1989   that analyse the @{ML_type_ind proof_body} data-structure from the
  2001   that analyse the @{ML_type_ind proof_body} data-structure from the
  1990   structure @{ML_struct Proofterm}.
  2002   structure @{ML_struct Proofterm}.
  1991 *}
  2003 *}
  1992 
  2004 
  1993 ML %grayML{*fun pthms_of (PBody {thms, ...}) = map #2 thms 
  2005 ML %grayML{*fun pthms_of (PBody {thms, ...}) = map #2 thms 
  1994 val get_names = map #1 o pthms_of 
  2006 val get_names = (map Proofterm.thm_node_name) o pthms_of 
  1995 val get_pbodies = map (Future.join o #3) o pthms_of *}
  2007 val get_pbodies = map (Future.join o Proofterm.thm_node_body) o pthms_of *}
  1996 
  2008 
  1997 text {* 
  2009 text {* 
  1998   To see what their purpose is, consider the following three short proofs.
  2010   To see what their purpose is, consider the following three short proofs.
  1999 *}
  2011 *}
  2000 
  2012 
  2246   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  2258   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  2247   to produce the ``symmetric'' version of an equation. The main function behind 
  2259   to produce the ``symmetric'' version of an equation. The main function behind 
  2248   this attribute is
  2260   this attribute is
  2249 *}
  2261 *}
  2250 
  2262 
  2251 ML %grayML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  2263 ML %grayML{*val my_symmetric = Thm.rule_attribute [] (fn _ => fn thm => thm RS @{thm sym})*}
  2252 
  2264 
  2253 text {* 
  2265 text {* 
  2254   where the function @{ML_ind  rule_attribute in Thm} expects a function taking a 
  2266   where the function @{ML_ind  rule_attribute in Thm} expects a function taking a 
  2255   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  2267   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  2256   returns another theorem (namely @{text thm} resolved with the theorem 
  2268   returns another theorem (namely @{text thm} resolved with the theorem 
  2311 
  2323 
  2312 ML %grayML{*fun MY_THEN thms = 
  2324 ML %grayML{*fun MY_THEN thms = 
  2313 let
  2325 let
  2314   fun RS_rev thm1 thm2 = thm2 RS thm1
  2326   fun RS_rev thm1 thm2 = thm2 RS thm1
  2315 in
  2327 in
  2316   Thm.rule_attribute (fn _ => fn thm => fold RS_rev thms thm)
  2328   Thm.rule_attribute [] (fn _ => fn thm => fold RS_rev thms thm)
  2317 end*}
  2329 end*}
  2318 
  2330 
  2319 text {* 
  2331 text {* 
  2320   where for convenience we define the reverse and curried version of @{ML RS}. 
  2332   where for convenience we define the reverse and curried version of @{ML RS}. 
  2321   The setup of this theorem attribute uses the parser @{ML thms in Attrib}, 
  2333   The setup of this theorem attribute uses the parser @{ML thms in Attrib}, 
  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"}