227 function below we mimic the behaviour of the usual pretty printer for |
218 function below we mimic the behaviour of the usual pretty printer for |
228 datatypes (it uses pretty-printing functions which will be explained in more |
219 datatypes (it uses pretty-printing functions which will be explained in more |
229 detail in Section~\ref{sec:pretty}). |
220 detail in Section~\ref{sec:pretty}). |
230 *} |
221 *} |
231 |
222 |
232 ML{*local |
223 ML %grayML{*local |
233 fun pp_pair (x, y) = Pretty.list "(" ")" [x, y] |
224 fun pp_pair (x, y) = Pretty.list "(" ")" [x, y] |
234 fun pp_list xs = Pretty.list "[" "]" xs |
225 fun pp_list xs = Pretty.list "[" "]" xs |
235 fun pp_str s = Pretty.str s |
226 fun pp_str s = Pretty.str s |
236 fun pp_qstr s = Pretty.quote (pp_str s) |
227 fun pp_qstr s = Pretty.quote (pp_str s) |
237 fun pp_int i = pp_str (string_of_int i) |
228 fun pp_int i = pp_str (string_of_int i) |
249 text {* |
240 text {* |
250 We can install this pretty printer with the function |
241 We can install this pretty printer with the function |
251 @{ML_ind addPrettyPrinter in PolyML} as follows. |
242 @{ML_ind addPrettyPrinter in PolyML} as follows. |
252 *} |
243 *} |
253 |
244 |
254 ML{*PolyML.addPrettyPrinter |
245 ML %grayML{*PolyML.addPrettyPrinter |
255 (fn _ => fn _ => ml_pretty o Pretty.to_ML o raw_pp_typ)*} |
246 (fn _ => fn _ => ml_pretty o Pretty.to_ML o raw_pp_typ)*} |
256 |
247 |
257 text {* |
248 text {* |
258 Now the type bool is printed out in full detail. |
249 Now the type bool is printed out in full detail. |
259 |
250 |
279 |
270 |
280 We can restore the usual behaviour of Isabelle's pretty printer |
271 We can restore the usual behaviour of Isabelle's pretty printer |
281 with the code |
272 with the code |
282 *} |
273 *} |
283 |
274 |
284 ML{*PolyML.addPrettyPrinter |
275 ML %grayML{*PolyML.addPrettyPrinter |
285 (fn _ => fn _ => ml_pretty o Pretty.to_ML o Proof_Display.pp_typ Pure.thy)*} |
276 (fn _ => fn _ => ml_pretty o Pretty.to_ML o Proof_Display.pp_typ Pure.thy)*} |
286 |
277 |
287 text {* |
278 text {* |
288 After that the types for booleans, lists and so on are printed out again |
279 After that the types for booleans, lists and so on are printed out again |
289 the standard Isabelle way. |
280 the standard Isabelle way. |
310 function that returns the implication @{text "\<And>(x::nat). P x \<Longrightarrow> Q x"} taking |
301 function that returns the implication @{text "\<And>(x::nat). P x \<Longrightarrow> Q x"} taking |
311 @{term P} and @{term Q} as arguments can only be written as: |
302 @{term P} and @{term Q} as arguments can only be written as: |
312 |
303 |
313 *} |
304 *} |
314 |
305 |
315 ML{*fun make_imp P Q = |
306 ML %grayML{*fun make_imp P Q = |
316 let |
307 let |
317 val x = Free ("x", @{typ nat}) |
308 val x = Free ("x", @{typ nat}) |
318 in |
309 in |
319 Logic.all x (Logic.mk_implies (P $ x, Q $ x)) |
310 Logic.all x (Logic.mk_implies (P $ x, Q $ x)) |
320 end *} |
311 end *} |
323 The reason is that you cannot pass the arguments @{term P} and @{term Q} |
314 The reason is that you cannot pass the arguments @{term P} and @{term Q} |
324 into an antiquotation.\footnote{At least not at the moment.} For example |
315 into an antiquotation.\footnote{At least not at the moment.} For example |
325 the following does \emph{not} work. |
316 the following does \emph{not} work. |
326 *} |
317 *} |
327 |
318 |
328 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *} |
319 ML %grayML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *} |
329 |
320 |
330 text {* |
321 text {* |
331 To see this, apply @{text "@{term S}"} and @{text "@{term T}"} |
322 To see this, apply @{text "@{term S}"} and @{text "@{term T}"} |
332 to both functions. With @{ML make_imp} you obtain the intended term involving |
323 to both functions. With @{ML make_imp} you obtain the intended term involving |
333 the given arguments |
324 the given arguments |
425 Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound |
416 Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound |
426 variables with terms. To see how this function works, let us implement a |
417 variables with terms. To see how this function works, let us implement a |
427 function that strips off the outermost forall quantifiers in a term. |
418 function that strips off the outermost forall quantifiers in a term. |
428 *} |
419 *} |
429 |
420 |
430 ML{*fun strip_alls t = |
421 ML %grayML{*fun strip_alls t = |
431 let |
422 let |
432 fun aux (x, T, t) = strip_alls t |>> cons (Free (x, T)) |
423 fun aux (x, T, t) = strip_alls t |>> cons (Free (x, T)) |
433 in |
424 in |
434 case t of |
425 case t of |
435 Const (@{const_name All}, _) $ Abs body => aux body |
426 Const (@{const_name All}, _) $ Abs body => aux body |
448 Note that we produced in the body two dangling de Bruijn indices. |
439 Note that we produced in the body two dangling de Bruijn indices. |
449 Later on we will also use the inverse function that |
440 Later on we will also use the inverse function that |
450 builds the quantification from a body and a list of (free) variables. |
441 builds the quantification from a body and a list of (free) variables. |
451 *} |
442 *} |
452 |
443 |
453 ML{*fun build_alls ([], t) = t |
444 ML %grayML{*fun build_alls ([], t) = t |
454 | build_alls (Free (x, T) :: vs, t) = |
445 | build_alls (Free (x, T) :: vs, t) = |
455 Const (@{const_name "All"}, (T --> @{typ bool}) --> @{typ bool}) |
446 Const (@{const_name "All"}, (T --> @{typ bool}) --> @{typ bool}) |
456 $ Abs (x, T, build_alls (vs, t))*} |
447 $ Abs (x, T, build_alls (vs, t))*} |
457 |
448 |
458 text {* |
449 text {* |
547 constants. They usually crop up when pattern matching terms or types, or |
538 constants. They usually crop up when pattern matching terms or types, or |
548 when constructing them. While it is perfectly ok to write the function |
539 when constructing them. While it is perfectly ok to write the function |
549 @{text is_true} as follows |
540 @{text is_true} as follows |
550 *} |
541 *} |
551 |
542 |
552 ML{*fun is_true @{term True} = true |
543 ML %grayML{*fun is_true @{term True} = true |
553 | is_true _ = false*} |
544 | is_true _ = false*} |
554 |
545 |
555 text {* |
546 text {* |
556 this does not work for picking out @{text "\<forall>"}-quantified terms. Because |
547 this does not work for picking out @{text "\<forall>"}-quantified terms. Because |
557 the function |
548 the function |
558 *} |
549 *} |
559 |
550 |
560 ML{*fun is_all (@{term All} $ _) = true |
551 ML %grayML{*fun is_all (@{term All} $ _) = true |
561 | is_all _ = false*} |
552 | is_all _ = false*} |
562 |
553 |
563 text {* |
554 text {* |
564 will not correctly match the formula @{prop[source] "\<forall>x::nat. P x"}: |
555 will not correctly match the formula @{prop[source] "\<forall>x::nat. P x"}: |
565 |
556 |
584 |
575 |
585 However there is still a problem: consider the similar function that |
576 However there is still a problem: consider the similar function that |
586 attempts to pick out @{text "Nil"}-terms: |
577 attempts to pick out @{text "Nil"}-terms: |
587 *} |
578 *} |
588 |
579 |
589 ML{*fun is_nil (Const ("Nil", _)) = true |
580 ML %grayML{*fun is_nil (Const ("Nil", _)) = true |
590 | is_nil _ = false *} |
581 | is_nil _ = false *} |
591 |
582 |
592 text {* |
583 text {* |
593 Unfortunately, also this function does \emph{not} work as expected, since |
584 Unfortunately, also this function does \emph{not} work as expected, since |
594 |
585 |
620 variable parts of the constant's name. Therefore a function for |
611 variable parts of the constant's name. Therefore a function for |
621 matching against constants that have a polymorphic type should |
612 matching against constants that have a polymorphic type should |
622 be written as follows. |
613 be written as follows. |
623 *} |
614 *} |
624 |
615 |
625 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true |
616 ML %grayML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true |
626 | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true |
617 | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true |
627 | is_nil_or_all _ = false *} |
618 | is_nil_or_all _ = false *} |
628 |
619 |
629 text {* |
620 text {* |
630 The antiquotation for properly referencing type constants is @{text "@{type_name \<dots>}"}. |
621 The antiquotation for properly referencing type constants is @{text "@{type_name \<dots>}"}. |
638 when defining constants. For example the function returning a function |
629 when defining constants. For example the function returning a function |
639 type is as follows: |
630 type is as follows: |
640 |
631 |
641 *} |
632 *} |
642 |
633 |
643 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *} |
634 ML %grayML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *} |
644 |
635 |
645 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *} |
636 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *} |
646 |
637 |
647 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *} |
638 ML %grayML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *} |
648 |
639 |
649 text {* |
640 text {* |
650 If you want to construct a function type with more than one argument |
641 If you want to construct a function type with more than one argument |
651 type, then you can use @{ML_ind "--->" in Term}. |
642 type, then you can use @{ML_ind "--->" in Term}. |
652 *} |
643 *} |
653 |
644 |
654 ML{*fun make_fun_types tys ty = tys ---> ty *} |
645 ML %grayML{*fun make_fun_types tys ty = tys ---> ty *} |
655 |
646 |
656 text {* |
647 text {* |
657 A handy function for manipulating terms is @{ML_ind map_types in Term}: it takes a |
648 A handy function for manipulating terms is @{ML_ind map_types in Term}: it takes a |
658 function and applies it to every type in a term. You can, for example, |
649 function and applies it to every type in a term. You can, for example, |
659 change every @{typ nat} in a term into an @{typ int} using the function: |
650 change every @{typ nat} in a term into an @{typ int} using the function: |
660 *} |
651 *} |
661 |
652 |
662 ML{*fun nat_to_int ty = |
653 ML %grayML{*fun nat_to_int ty = |
663 (case ty of |
654 (case ty of |
664 @{typ nat} => @{typ int} |
655 @{typ nat} => @{typ int} |
665 | Type (s, tys) => Type (s, map nat_to_int tys) |
656 | Type (s, tys) => Type (s, map nat_to_int tys) |
666 | _ => ty)*} |
657 | _ => ty)*} |
667 |
658 |
800 |
791 |
801 text_raw {* |
792 text_raw {* |
802 \begin{figure}[t] |
793 \begin{figure}[t] |
803 \begin{minipage}{\textwidth} |
794 \begin{minipage}{\textwidth} |
804 \begin{isabelle}*} |
795 \begin{isabelle}*} |
805 ML{*fun pretty_helper aux env = |
796 ML %grayML{*fun pretty_helper aux env = |
806 env |> Vartab.dest |
797 env |> Vartab.dest |
807 |> map aux |
798 |> map aux |
808 |> map (fn (s1, s2) => Pretty.block [s1, Pretty.str " := ", s2]) |
799 |> map (fn (s1, s2) => Pretty.block [s1, Pretty.str " := ", s2]) |
809 |> Pretty.enum "," "[" "]" |
800 |> Pretty.enum "," "[" "]" |
810 |> pwriteln |
801 |> pwriteln |
862 *} |
853 *} |
863 |
854 |
864 class s1 |
855 class s1 |
865 class s2 |
856 class s2 |
866 |
857 |
867 ML{*val (tyenv, index) = let |
858 ML %grayML{*val (tyenv, index) = let |
868 val ty1 = @{typ_pat "?'a::s1"} |
859 val ty1 = @{typ_pat "?'a::s1"} |
869 val ty2 = @{typ_pat "?'b::s2"} |
860 val ty2 = @{typ_pat "?'b::s2"} |
870 in |
861 in |
871 Sign.typ_unify @{theory} (ty1, ty2) (Vartab.empty, 0) |
862 Sign.typ_unify @{theory} (ty1, ty2) (Vartab.empty, 0) |
872 end*} |
863 end*} |
914 also from the structure @{ML_struct Sign}. This function returns a @{ML_type |
905 also from the structure @{ML_struct Sign}. This function returns a @{ML_type |
915 Type.tyenv} as well, but might raise the exception @{text TYPE_MATCH} in case |
906 Type.tyenv} as well, but might raise the exception @{text TYPE_MATCH} in case |
916 of failure. For example |
907 of failure. For example |
917 *} |
908 *} |
918 |
909 |
919 ML{*val tyenv_match = let |
910 ML %grayML{*val tyenv_match = let |
920 val pat = @{typ_pat "?'a * ?'b"} |
911 val pat = @{typ_pat "?'a * ?'b"} |
921 and ty = @{typ_pat "bool list * nat"} |
912 and ty = @{typ_pat "bool list * nat"} |
922 in |
913 in |
923 Sign.typ_match @{theory} (pat, ty) Vartab.empty |
914 Sign.typ_match @{theory} (pat, ty) Vartab.empty |
924 end*} |
915 end*} |
942 @{ML subst_type in Envir} for matchers and @{ML norm_type in Envir} |
933 @{ML subst_type in Envir} for matchers and @{ML norm_type in Envir} |
943 for unifiers. To show the difference, let us calculate the |
934 for unifiers. To show the difference, let us calculate the |
944 following matcher: |
935 following matcher: |
945 *} |
936 *} |
946 |
937 |
947 ML{*val tyenv_match' = let |
938 ML %grayML{*val tyenv_match' = let |
948 val pat = @{typ_pat "?'a * ?'b"} |
939 val pat = @{typ_pat "?'a * ?'b"} |
949 and ty = @{typ_pat "?'b list * nat"} |
940 and ty = @{typ_pat "?'b list * nat"} |
950 in |
941 in |
951 Sign.typ_match @{theory} (pat, ty) Vartab.empty |
942 Sign.typ_match @{theory} (pat, ty) Vartab.empty |
952 end*} |
943 end*} |
987 first_order_match in Pattern} for terms. This matching function returns a |
978 first_order_match in Pattern} for terms. This matching function returns a |
988 type environment and a term environment. To pretty print the latter we use |
979 type environment and a term environment. To pretty print the latter we use |
989 the function @{text "pretty_env"}: |
980 the function @{text "pretty_env"}: |
990 *} |
981 *} |
991 |
982 |
992 ML{*fun pretty_env ctxt env = |
983 ML %grayML{*fun pretty_env ctxt env = |
993 let |
984 let |
994 fun get_trms (v, (T, t)) = (Var (v, T), t) |
985 fun get_trms (v, (T, t)) = (Var (v, T), t) |
995 val print = pairself (pretty_term ctxt) |
986 val print = pairself (pretty_term ctxt) |
996 in |
987 in |
997 pretty_helper (print o get_trms) env |
988 pretty_helper (print o get_trms) env |
1002 a schematic term variable with a type and a term. An example of a first-order |
993 a schematic term variable with a type and a term. An example of a first-order |
1003 matching problem is the term @{term "P (\<lambda>a b. Q b a)"} and the pattern |
994 matching problem is the term @{term "P (\<lambda>a b. Q b a)"} and the pattern |
1004 @{text "?X ?Y"}. |
995 @{text "?X ?Y"}. |
1005 *} |
996 *} |
1006 |
997 |
1007 ML{*val (_, fo_env) = let |
998 ML %grayML{*val (_, fo_env) = let |
1008 val fo_pat = @{term_pat "(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y"} |
999 val fo_pat = @{term_pat "(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y"} |
1009 val trm_a = @{term "P::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool"} |
1000 val trm_a = @{term "P::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool"} |
1010 val trm_b = @{term "\<lambda>a b. (Q::nat\<Rightarrow>nat\<Rightarrow>nat) b a"} |
1001 val trm_b = @{term "\<lambda>a b. (Q::nat\<Rightarrow>nat\<Rightarrow>nat) b a"} |
1011 val init = (Vartab.empty, Vartab.empty) |
1002 val init = (Vartab.empty, Vartab.empty) |
1012 in |
1003 in |
1121 not posses a single most general solution. Therefore Isabelle implements the |
1112 not posses a single most general solution. Therefore Isabelle implements the |
1122 unification function @{ML_ind unifiers in Unify} so that it returns a lazy |
1113 unification function @{ML_ind unifiers in Unify} so that it returns a lazy |
1123 list of potentially infinite unifiers. An example is as follows |
1114 list of potentially infinite unifiers. An example is as follows |
1124 *} |
1115 *} |
1125 |
1116 |
1126 ML{*val uni_seq = |
1117 ML %grayML{*val uni_seq = |
1127 let |
1118 let |
1128 val trm1 = @{term_pat "?X ?Y"} |
1119 val trm1 = @{term_pat "?X ?Y"} |
1129 val trm2 = @{term "f a"} |
1120 val trm2 = @{term "f a"} |
1130 val init = Envir.empty 0 |
1121 val init = Envir.empty 0 |
1131 in |
1122 in |
1136 The unifiers can be extracted from the lazy sequence using the |
1127 The unifiers can be extracted from the lazy sequence using the |
1137 function @{ML_ind "Seq.pull"}. In the example we obtain three |
1128 function @{ML_ind "Seq.pull"}. In the example we obtain three |
1138 unifiers @{text "un1\<dots>un3"}. |
1129 unifiers @{text "un1\<dots>un3"}. |
1139 *} |
1130 *} |
1140 |
1131 |
1141 ML{*val SOME ((un1, _), next1) = Seq.pull uni_seq; |
1132 ML %grayML{*val SOME ((un1, _), next1) = Seq.pull uni_seq; |
1142 val SOME ((un2, _), next2) = Seq.pull next1; |
1133 val SOME ((un2, _), next2) = Seq.pull next1; |
1143 val SOME ((un3, _), next3) = Seq.pull next2; |
1134 val SOME ((un3, _), next3) = Seq.pull next2; |
1144 val NONE = Seq.pull next3 *} |
1135 val NONE = Seq.pull next3 *} |
1145 |
1136 |
1146 text {* |
1137 text {* |
1224 from an environment the corresponding variable mappings for schematic type |
1215 from an environment the corresponding variable mappings for schematic type |
1225 and term variables. These mappings can be turned into proper |
1216 and term variables. These mappings can be turned into proper |
1226 @{ML_type ctyp}-pairs with the function |
1217 @{ML_type ctyp}-pairs with the function |
1227 *} |
1218 *} |
1228 |
1219 |
1229 ML{*fun prep_trm thy (x, (T, t)) = |
1220 ML %grayML{*fun prep_trm thy (x, (T, t)) = |
1230 (cterm_of thy (Var (x, T)), cterm_of thy t)*} |
1221 (cterm_of thy (Var (x, T)), cterm_of thy t)*} |
1231 |
1222 |
1232 text {* |
1223 text {* |
1233 and into proper @{ML_type cterm}-pairs with |
1224 and into proper @{ML_type cterm}-pairs with |
1234 *} |
1225 *} |
1235 |
1226 |
1236 ML{*fun prep_ty thy (x, (S, ty)) = |
1227 ML %grayML{*fun prep_ty thy (x, (S, ty)) = |
1237 (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)*} |
1228 (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)*} |
1238 |
1229 |
1239 text {* |
1230 text {* |
1240 We can now calculate the instantiations from the matching function. |
1231 We can now calculate the instantiations from the matching function. |
1241 *} |
1232 *} |
1626 also implements a mechanism where a theorem name can refer to a custom theorem |
1617 also implements a mechanism where a theorem name can refer to a custom theorem |
1627 list. For this you can use the function @{ML_ind add_thms_dynamic in Global_Theory}. |
1618 list. For this you can use the function @{ML_ind add_thms_dynamic in Global_Theory}. |
1628 To see how it works let us assume we defined our own theorem list @{text MyThmList}. |
1619 To see how it works let us assume we defined our own theorem list @{text MyThmList}. |
1629 *} |
1620 *} |
1630 |
1621 |
1631 ML{*structure MyThmList = Generic_Data |
1622 ML %grayML{*structure MyThmList = Generic_Data |
1632 (type T = thm list |
1623 (type T = thm list |
1633 val empty = [] |
1624 val empty = [] |
1634 val extend = I |
1625 val extend = I |
1635 val merge = merge Thm.eq_thm_prop) |
1626 val merge = merge Thm.eq_thm_prop) |
1636 |
1627 |
1807 @{text "?list"}. For this we can use the function |
1798 @{text "?list"}. For this we can use the function |
1808 @{ML_ind forall_intr_vars in Drule}. This allows us to implement the |
1799 @{ML_ind forall_intr_vars in Drule}. This allows us to implement the |
1809 following function for atomizing a theorem. |
1800 following function for atomizing a theorem. |
1810 *} |
1801 *} |
1811 |
1802 |
1812 ML{*fun atomize_thm thm = |
1803 ML %grayML{*fun atomize_thm thm = |
1813 let |
1804 let |
1814 val thm' = forall_intr_vars thm |
1805 val thm' = forall_intr_vars thm |
1815 val thm'' = Object_Logic.atomize (cprop_of thm') |
1806 val thm'' = Object_Logic.atomize (cprop_of thm') |
1816 in |
1807 in |
1817 Raw_Simplifier.rewrite_rule [thm''] thm' |
1808 Raw_Simplifier.rewrite_rule [thm''] thm' |
1848 There is also the possibility of proving multiple goals at the same time |
1839 There is also the possibility of proving multiple goals at the same time |
1849 using the function @{ML_ind prove_multi in Goal}. For this let us define the |
1840 using the function @{ML_ind prove_multi in Goal}. For this let us define the |
1850 following three helper functions. |
1841 following three helper functions. |
1851 *} |
1842 *} |
1852 |
1843 |
1853 ML{*fun rep_goals i = replicate i @{prop "f x = f x"} |
1844 ML %grayML{*fun rep_goals i = replicate i @{prop "f x = f x"} |
1854 fun rep_tacs i = replicate i (rtac @{thm refl}) |
1845 fun rep_tacs i = replicate i (rtac @{thm refl}) |
1855 |
1846 |
1856 fun multi_test ctxt i = |
1847 fun multi_test ctxt i = |
1857 Goal.prove_multi ctxt ["f", "x"] [] (rep_goals i) |
1848 Goal.prove_multi ctxt ["f", "x"] [] (rep_goals i) |
1858 (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*} |
1849 (K ((Goal.conjunction_tac THEN' RANGE (rep_tacs i)) 1))*} |
1869 large goals. If you increase the counter in the code above to @{text 3000}, |
1860 large goals. If you increase the counter in the code above to @{text 3000}, |
1870 you will notice that takes approximately ten(!) times longer than |
1861 you will notice that takes approximately ten(!) times longer than |
1871 using @{ML map} and @{ML prove in Goal}. |
1862 using @{ML map} and @{ML prove in Goal}. |
1872 *} |
1863 *} |
1873 |
1864 |
1874 ML{*let |
1865 ML %grayML{*let |
1875 fun test_prove ctxt thm = |
1866 fun test_prove ctxt thm = |
1876 Goal.prove ctxt ["P", "x"] [] thm (K (rtac @{thm refl} 1)) |
1867 Goal.prove ctxt ["P", "x"] [] thm (K (rtac @{thm refl} 1)) |
1877 in |
1868 in |
1878 map (test_prove @{context}) (rep_goals 3000) |
1869 map (test_prove @{context}) (rep_goals 3000) |
1879 end*} |
1870 end*} |
2038 giving a list of strings that should be used for the replacement of the |
2029 giving a list of strings that should be used for the replacement of the |
2039 variables. For this we implement the function which takes a list of strings |
2030 variables. For this we implement the function which takes a list of strings |
2040 and uses them as name in the outermost abstractions. |
2031 and uses them as name in the outermost abstractions. |
2041 *} |
2032 *} |
2042 |
2033 |
2043 ML{*fun rename_allq [] t = t |
2034 ML %grayML{*fun rename_allq [] t = t |
2044 | rename_allq (x::xs) (Const (@{const_name "All"}, U) $ Abs (_, T, t)) = |
2035 | rename_allq (x::xs) (Const (@{const_name "All"}, U) $ Abs (_, T, t)) = |
2045 Const (@{const_name "All"}, U) $ Abs (x, T, rename_allq xs t) |
2036 Const (@{const_name "All"}, U) $ Abs (x, T, rename_allq xs t) |
2046 | rename_allq xs (Const (@{const_name "Trueprop"}, U) $ t) = |
2037 | rename_allq xs (Const (@{const_name "Trueprop"}, U) $ t) = |
2047 rename_allq xs t |
2038 rename_allq xs t |
2048 | rename_allq _ t = t*} |
2039 | rename_allq _ t = t*} |
2115 version of the attribute @{text "[symmetric]"}. The purpose of this attribute is |
2106 version of the attribute @{text "[symmetric]"}. The purpose of this attribute is |
2116 to produce the ``symmetric'' version of an equation. The main function behind |
2107 to produce the ``symmetric'' version of an equation. The main function behind |
2117 this attribute is |
2108 this attribute is |
2118 *} |
2109 *} |
2119 |
2110 |
2120 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*} |
2111 ML %grayML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*} |
2121 |
2112 |
2122 text {* |
2113 text {* |
2123 where the function @{ML_ind rule_attribute in Thm} expects a function taking a |
2114 where the function @{ML_ind rule_attribute in Thm} expects a function taking a |
2124 context (which we ignore in the code above) and a theorem (@{text thm}), and |
2115 context (which we ignore in the code above) and a theorem (@{text thm}), and |
2125 returns another theorem (namely @{text thm} resolved with the theorem |
2116 returns another theorem (namely @{text thm} resolved with the theorem |
2162 An alternative for setting up an attribute is the function @{ML_ind setup in Attrib}. |
2153 An alternative for setting up an attribute is the function @{ML_ind setup in Attrib}. |
2163 So instead of using \isacommand{attribute\_setup}, you can also set up the |
2154 So instead of using \isacommand{attribute\_setup}, you can also set up the |
2164 attribute as follows: |
2155 attribute as follows: |
2165 *} |
2156 *} |
2166 |
2157 |
2167 ML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric) |
2158 ML %grayML{*Attrib.setup @{binding "my_sym"} (Scan.succeed my_symmetric) |
2168 "applying the sym rule" *} |
2159 "applying the sym rule" *} |
2169 |
2160 |
2170 text {* |
2161 text {* |
2171 This gives a function from @{ML_type "theory -> theory"}, which |
2162 This gives a function from @{ML_type "theory -> theory"}, which |
2172 can be used for example with \isacommand{setup} or with |
2163 can be used for example with \isacommand{setup} or with |
2176 our own version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems |
2167 our own version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems |
2177 as argument and resolve the theorem with this list (one theorem |
2168 as argument and resolve the theorem with this list (one theorem |
2178 after another). The code for this attribute is |
2169 after another). The code for this attribute is |
2179 *} |
2170 *} |
2180 |
2171 |
2181 ML{*fun MY_THEN thms = |
2172 ML %grayML{*fun MY_THEN thms = |
2182 let |
2173 let |
2183 fun RS_rev thm1 thm2 = thm2 RS thm1 |
2174 fun RS_rev thm1 thm2 = thm2 RS thm1 |
2184 in |
2175 in |
2185 Thm.rule_attribute (fn _ => fn thm => fold RS_rev thms thm) |
2176 Thm.rule_attribute (fn _ => fn thm => fold RS_rev thms thm) |
2186 end*} |
2177 end*} |
2235 or deletes a theorem from the current simpset. For these applications, you |
2226 or deletes a theorem from the current simpset. For these applications, you |
2236 can use @{ML_ind declaration_attribute in Thm}. To illustrate this function, |
2227 can use @{ML_ind declaration_attribute in Thm}. To illustrate this function, |
2237 let us introduce a theorem list. |
2228 let us introduce a theorem list. |
2238 *} |
2229 *} |
2239 |
2230 |
2240 ML{*structure MyThms = Named_Thms |
2231 ML %grayML{*structure MyThms = Named_Thms |
2241 (val name = @{binding "attr_thms"} |
2232 (val name = @{binding "attr_thms"} |
2242 val description = "Theorems for an Attribute") *} |
2233 val description = "Theorems for an Attribute") *} |
2243 |
2234 |
2244 text {* |
2235 text {* |
2245 We are going to modify this list by adding and deleting theorems. |
2236 We are going to modify this list by adding and deleting theorems. |
2246 For this we use the two functions @{ML MyThms.add_thm} and |
2237 For this we use the two functions @{ML MyThms.add_thm} and |
2247 @{ML MyThms.del_thm}. You can turn them into attributes |
2238 @{ML MyThms.del_thm}. You can turn them into attributes |
2248 with the code |
2239 with the code |
2249 *} |
2240 *} |
2250 |
2241 |
2251 ML{*val my_add = Thm.declaration_attribute MyThms.add_thm |
2242 ML %grayML{*val my_add = Thm.declaration_attribute MyThms.add_thm |
2252 val my_del = Thm.declaration_attribute MyThms.del_thm *} |
2243 val my_del = Thm.declaration_attribute MyThms.del_thm *} |
2253 |
2244 |
2254 text {* |
2245 text {* |
2255 and set up the attributes as follows |
2246 and set up the attributes as follows |
2256 *} |
2247 *} |
2340 string}. This can be done with the function @{ML_ind string_of in Pretty}. In what |
2331 string}. This can be done with the function @{ML_ind string_of in Pretty}. In what |
2341 follows we will use the following wrapper function for printing a pretty |
2332 follows we will use the following wrapper function for printing a pretty |
2342 type: |
2333 type: |
2343 *} |
2334 *} |
2344 |
2335 |
2345 ML{*fun pprint prt = tracing (Pretty.string_of prt)*} |
2336 ML %grayML{*fun pprint prt = tracing (Pretty.string_of prt)*} |
2346 |
2337 |
2347 text {* |
2338 text {* |
2348 The point of the pretty-printing infrastructure is to give hints about how to |
2339 The point of the pretty-printing infrastructure is to give hints about how to |
2349 layout text and let Isabelle do the actual layout. Let us first explain |
2340 layout text and let Isabelle do the actual layout. Let us first explain |
2350 how you can insert places where a line break can occur. For this assume the |
2341 how you can insert places where a line break can occur. For this assume the |
2351 following function that replicates a string n times: |
2342 following function that replicates a string n times: |
2352 *} |
2343 *} |
2353 |
2344 |
2354 ML{*fun rep n str = implode (replicate n str) *} |
2345 ML %grayML{*fun rep n str = implode (replicate n str) *} |
2355 |
2346 |
2356 text {* |
2347 text {* |
2357 and suppose we want to print out the string: |
2348 and suppose we want to print out the string: |
2358 *} |
2349 *} |
2359 |
2350 |
2360 ML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*} |
2351 ML %grayML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*} |
2361 |
2352 |
2362 text {* |
2353 text {* |
2363 We deliberately chose a large string so that it spans over more than one line. |
2354 We deliberately chose a large string so that it spans over more than one line. |
2364 If we print out the string using the usual ``quick-and-dirty'' method, then |
2355 If we print out the string using the usual ``quick-and-dirty'' method, then |
2365 we obtain the ugly output: |
2356 we obtain the ugly output: |