39 \end{isabelle} |
39 \end{isabelle} |
40 |
40 |
41 Like normal Isabelle proof scripts, \isacommand{ML}-commands can be |
41 Like normal Isabelle proof scripts, \isacommand{ML}-commands can be |
42 evaluated by using the advance and undo buttons of your Isabelle |
42 evaluated by using the advance and undo buttons of your Isabelle |
43 environment. The code inside the \isacommand{ML}-command can also contain |
43 environment. The code inside the \isacommand{ML}-command can also contain |
44 value and function bindings, and even those can be undone when the proof |
44 value and function bindings, for example |
45 script is retracted. As mentioned in the Introduction, we will drop the |
45 *} |
|
46 |
|
47 ML %gray {* |
|
48 val r = ref 0 |
|
49 fun f n = n + 1 |
|
50 *} |
|
51 |
|
52 text {* |
|
53 and even those can be undone when the proof |
|
54 script is retracted. As mentioned in the Introduction, we will drop the |
46 \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} scaffolding whenever we |
55 \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} scaffolding whenever we |
47 show code. The lines prefixed with @{text [quotes] ">"} are not part of the |
56 show code. The lines prefixed with @{text [quotes] ">"} are not part of the |
48 code, rather they indicate what the response is when the code is evaluated. |
57 code, rather they indicate what the response is when the code is evaluated. |
49 |
58 |
50 Once a portion of code is relatively stable, you usually want to export it |
59 Once a portion of code is relatively stable, you usually want to export it |
285 |
294 |
286 In the context of Isabelle, a ``real world'' example for a function written in |
295 In the context of Isabelle, a ``real world'' example for a function written in |
287 the waterfall fashion might be the following code: |
296 the waterfall fashion might be the following code: |
288 *} |
297 *} |
289 |
298 |
290 ML %linenosgray{*fun apply_fresh_args pred ctxt = |
299 ML %linenosgray{*fun apply_fresh_args f ctxt = |
291 pred |> fastype_of |
300 f |> fastype_of |
292 |> binder_types |
301 |> binder_types |
293 |> map (pair "z") |
302 |> map (pair "z") |
294 |> Variable.variant_frees ctxt [pred] |
303 |> Variable.variant_frees ctxt [f] |
295 |> map Free |
304 |> map Free |
296 |> (curry list_comb) pred *} |
305 |> (curry list_comb) f *} |
297 |
306 |
298 text {* |
307 text {* |
299 This code extracts the argument types of a given |
308 This code extracts the argument types of a given function and then generates |
300 predicate and then generates for each argument type a distinct variable; finally it |
309 for each argument type a distinct variable; finally it applies the generated |
301 applies the generated variables to the predicate. For example |
310 variables to the function. For example |
302 |
311 |
303 @{ML_response_fake [display,gray] |
312 @{ML_response_fake [display,gray] |
304 "apply_fresh_args @{term \"P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool\"} @{context} |
313 "apply_fresh_args @{term \"P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool\"} @{context} |
305 |> Syntax.string_of_term @{context} |
314 |> Syntax.string_of_term @{context} |
306 |> warning" |
315 |> warning" |
307 "P z za zb"} |
316 "P z za zb"} |
308 |
317 |
309 You can read off this behaviour from how @{ML apply_fresh_args} is |
318 You can read off this behaviour from how @{ML apply_fresh_args} is |
310 coded: in Line 2, the function @{ML fastype_of} calculates the type of the |
319 coded: in Line 2, the function @{ML fastype_of} calculates the type of the |
311 predicate; @{ML binder_types} in the next line produces the list of argument |
320 function; @{ML binder_types} in the next line produces the list of argument |
312 types (in the case above the list @{text "[nat, int, unit]"}); Line 4 |
321 types (in the case above the list @{text "[nat, int, unit]"}); Line 4 |
313 pairs up each type with the string @{text "z"}; the |
322 pairs up each type with the string @{text "z"}; the |
314 function @{ML variant_frees in Variable} generates for each @{text "z"} a |
323 function @{ML variant_frees in Variable} generates for each @{text "z"} a |
315 unique name avoiding the given @{text pred}; the list of name-type pairs is turned |
324 unique name avoiding the given @{text f}; the list of name-type pairs is turned |
316 into a list of variable terms in Line 6, which in the last line is applied |
325 into a list of variable terms in Line 6, which in the last line is applied |
317 by the function @{ML list_comb} to the predicate. We have to use the |
326 by the function @{ML list_comb} to the function. We have to use the |
318 function @{ML curry}, because @{ML list_comb} expects the predicate and the |
327 function @{ML curry}, because @{ML list_comb} expects the function and the |
319 variables list as a pair. |
328 variables list as a pair. |
320 |
329 |
321 The combinator @{ML "#>"} is the reverse function composition. It can be |
330 The combinator @{ML "#>"} is the reverse function composition. It can be |
322 used to define the following function |
331 used to define the following function |
323 *} |
332 *} |
627 |
658 |
628 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *} |
659 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *} |
629 |
660 |
630 text {* |
661 text {* |
631 To see this apply @{text "@{term S}"} and @{text "@{term T}"} |
662 To see this apply @{text "@{term S}"} and @{text "@{term T}"} |
632 to both functions. With @{ML make_imp} we obtain the intended term involving |
663 to both functions. With @{ML make_imp} you obtain the intended term involving |
633 the given arguments |
664 the given arguments |
634 |
665 |
635 @{ML_response [display,gray] "make_imp @{term S} @{term T}" |
666 @{ML_response [display,gray] "make_imp @{term S} @{term T}" |
636 "Const \<dots> $ |
667 "Const \<dots> $ |
637 Abs (\"x\", Type (\"nat\",[]), |
668 Abs (\"x\", Type (\"nat\",[]), |
638 Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ (Free (\"T\",\<dots>) $ \<dots>))"} |
669 Const \<dots> $ (Free (\"S\",\<dots>) $ \<dots>) $ (Free (\"T\",\<dots>) $ \<dots>))"} |
639 |
670 |
640 whereas with @{ML make_wrong_imp} we obtain a term involving the @{term "P"} |
671 whereas with @{ML make_wrong_imp} you obtain a term involving the @{term "P"} |
641 and @{text "Q"} from the antiquotation. |
672 and @{text "Q"} from the antiquotation. |
642 |
673 |
643 @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T}" |
674 @{ML_response [display,gray] "make_wrong_imp @{term S} @{term T}" |
644 "Const \<dots> $ |
675 "Const \<dots> $ |
645 Abs (\"x\", \<dots>, |
676 Abs (\"x\", \<dots>, |
646 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
677 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
647 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
678 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
648 |
679 |
649 There are a number of handy functions that are frequently used for |
680 There are a number of handy functions that are frequently used for |
650 constructing terms. One is the function @{ML list_comb} which a term |
681 constructing terms. One is the function @{ML list_comb}, which takes |
651 and a list of terms as argument, and produces as output the term |
682 a term and a list of terms as argument, and produces as output the term |
652 list applied to the term. For example |
683 list applied to the term. For example |
653 |
684 |
654 @{ML_response_fake [display,gray] |
685 @{ML_response_fake [display,gray] |
655 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])" |
686 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])" |
656 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
687 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
657 |
688 |
658 (FIXME: handy functions for constructing terms: @{ML lambda}, |
689 Another handy function is @{ML lambda}, which abstracts a variable |
659 @{ML subst_free}) |
690 in a term. For example |
660 *} |
691 |
661 |
692 @{ML_response_fake [display,gray] |
662 ML {* lambda @{term "x::nat"} @{term "P x"}*} |
693 "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}" |
663 |
694 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
664 |
695 |
665 text {* |
696 In the example @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
666 As can be seen this function does not take the typing annotation into account. |
697 and an abstraction. It also records the type of the abstracted |
|
698 variable and for printing purposes also its name. Note that because of the |
|
699 typing annotation on @{text "P"}, the variable @{text "x"} in @{text "P x"} |
|
700 is of the same type as the abstracted variable. If it is of different type, |
|
701 as in |
|
702 |
|
703 @{ML_response_fake [display,gray] |
|
704 "lambda @{term \"x::nat\"} @{term \"(P::bool\<Rightarrow>bool) x\"}" |
|
705 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Free (\"x\", \"bool\"))"} |
|
706 |
|
707 then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. |
|
708 This is a fundamental principle |
|
709 of Church-style typing, where variables with the same name still differ, if they |
|
710 have different type. |
|
711 |
|
712 There is also the function @{ML subst_free} with which terms can |
|
713 be replaced by other terms. For example below we replace in @{term "f 0 x"} |
|
714 the subterm @{term "f 0"} by @{term y} and @{term x} by @{term True}. |
|
715 |
|
716 @{ML_response_fake [display,gray] |
|
717 "subst_free [(@{term \"(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0\"}, @{term \"y::nat\<Rightarrow>nat\"}), |
|
718 (@{term \"x::nat\"}, @{term \"True\"})] |
|
719 @{term \"((f::nat\<Rightarrow>nat\<Rightarrow>nat) 0) x\"}" |
|
720 "Free (\"y\", \"nat \<Rightarrow> nat\") $ Const (\"True\", \"bool\")"} |
|
721 |
|
722 As can be seen, @{ML subst_free} does not take typability into account. |
|
723 However it takes alpha-equivalence into account: |
|
724 |
|
725 @{ML_response_fake [display, gray] |
|
726 "subst_free [(@{term \"(\<lambda>y::nat. y)\"}, @{term \"x::nat\"})] |
|
727 @{term \"(\<lambda>x::nat. x)\"}" |
|
728 "Free (\"x\", \"nat\")"} |
667 |
729 |
668 \begin{readmore} |
730 \begin{readmore} |
669 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and |
731 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and |
670 @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms |
732 @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms |
671 and types easier.\end{readmore} |
733 and types easier.\end{readmore} |
672 |
734 |
673 Have a look at these files and try to solve the following two exercises: |
735 Have a look at these files and try to solve the following two exercises: |
674 *} |
|
675 |
|
676 text {* |
|
677 |
736 |
678 \begin{exercise}\label{fun:revsum} |
737 \begin{exercise}\label{fun:revsum} |
679 Write a function @{text "rev_sum : term -> term"} that takes a |
738 Write a function @{text "rev_sum : term -> term"} that takes a |
680 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "n"} might be zero) |
739 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "n"} might be zero) |
681 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume |
740 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume |
880 \begin{exercise} |
939 \begin{exercise} |
881 Check that the function defined in Exercise~\ref{fun:revsum} returns a |
940 Check that the function defined in Exercise~\ref{fun:revsum} returns a |
882 result that type-checks. |
941 result that type-checks. |
883 \end{exercise} |
942 \end{exercise} |
884 |
943 |
885 Remember Isabelle foolows the Church-style typing for terms, i.e.~a term contains |
944 Remember Isabelle follows the Church-style typing for terms, i.e.~a term contains |
886 enough typing information (constants, free variables and abstractions all have typing |
945 enough typing information (constants, free variables and abstractions all have typing |
887 information) so that it is always clear what the type of a term is. |
946 information) so that it is always clear what the type of a term is. |
888 Given a well-typed term, the function @{ML type_of} returns the |
947 Given a well-typed term, the function @{ML type_of} returns the |
889 type of a term. Consider for example: |
948 type of a term. Consider for example: |
890 |
949 |
891 @{ML_response [display,gray] |
950 @{ML_response [display,gray] |
892 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"} |
951 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"} |
893 |
952 |
894 To calculate the type, this function traverses the whole term and will |
953 To calculate the type, this function traverses the whole term and will |
895 detect any typing inconsistency. For examle changing the type of the variable |
954 detect any typing inconsistency. For example changing the type of the variable |
896 @{term "x"} from @{typ "nat"} to @{typ "int"} will result in the error message: |
955 @{term "x"} from @{typ "nat"} to @{typ "int"} will result in the error message: |
897 |
956 |
898 @{ML_response_fake [display,gray] |
957 @{ML_response_fake [display,gray] |
899 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" |
958 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" |
900 "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"} |
959 "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"} |
930 end" |
989 end" |
931 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $ |
990 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $ |
932 Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"} |
991 Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"} |
933 |
992 |
934 Instead of giving explicitly the type for the constant @{text "plus"} and the free |
993 Instead of giving explicitly the type for the constant @{text "plus"} and the free |
935 variable @{text "x"}, the type-inference filles in the missing information. |
994 variable @{text "x"}, the type-inference fills in the missing information. |
936 |
995 |
937 \begin{readmore} |
996 \begin{readmore} |
938 See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading, |
997 See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading, |
939 checking and pretty-printing of terms are defined. Fuctions related to the |
998 checking and pretty-printing of terms are defined. Functions related to the |
940 type inference are implemented in @{ML_file "Pure/type.ML"} and |
999 type inference are implemented in @{ML_file "Pure/type.ML"} and |
941 @{ML_file "Pure/type_infer.ML"}. |
1000 @{ML_file "Pure/type_infer.ML"}. |
942 \end{readmore} |
1001 \end{readmore} |
943 |
1002 |
944 (FIXME: say something about sorts) |
1003 (FIXME: say something about sorts) |
1011 *} |
1070 *} |
1012 |
1071 |
1013 section {* Theorem Attributes *} |
1072 section {* Theorem Attributes *} |
1014 |
1073 |
1015 text {* |
1074 text {* |
1016 Theorem attributes are @{text "[simp]"}, @{text "[OF \<dots>]"}, @{text |
1075 Theorem attributes are @{text "[symmetric]"}, @{text "[THEN \<dots>]"}, @{text |
1017 "[symmetric]"} and so on. Such attributes are \emph{neither} tags \emph{nor} flags |
1076 "[simp]"} and so on. Such attributes are \emph{neither} tags \emph{nor} flags |
1018 annotated to theorems, but functions that do further processing once a |
1077 annotated to theorems, but functions that do further processing once a |
1019 theorem is proven. In particular, it is not possible to find out |
1078 theorem is proved. In particular, it is not possible to find out |
1020 what are all theorems that have a given attribute in common, unless of course |
1079 what are all theorems that have a given attribute in common, unless of course |
1021 the function behind the attribute stores the theorems in a retrivable |
1080 the function behind the attribute stores the theorems in a retrievable |
1022 datastructure. |
1081 datastructure. |
1023 |
1082 |
1024 If you want to print out all currently known attributes a theorem |
1083 If you want to print out all currently known attributes a theorem can have, |
1025 can have, you can use the function: |
1084 you can use the Isabelle command |
1026 |
1085 |
1027 @{ML_response_fake [display,gray] "Attrib.print_attributes @{theory}" |
1086 \begin{isabelle} |
1028 "COMP: direct composition with rules (no lifting) |
1087 \isacommand{print\_attributes}\\ |
1029 HOL.dest: declaration of Classical destruction rule |
1088 @{text "> COMP: direct composition with rules (no lifting)"}\\ |
1030 HOL.elim: declaration of Classical elimination rule |
1089 @{text "> HOL.dest: declaration of Classical destruction rule"}\\ |
1031 \<dots>"} |
1090 @{text "> HOL.elim: declaration of Classical elimination rule"}\\ |
|
1091 @{text "> \<dots>"} |
|
1092 \end{isabelle} |
|
1093 |
|
1094 The theorem attributes fall roughly into two categories: the first category manipulates |
|
1095 the proved theorem (like @{text "[symmetric]"} and @{text "[THEN \<dots>]"}), and the second |
|
1096 stores the proved theorem somewhere as data (like @{text "[simp]"}, which adds |
|
1097 the theorem to the current simpset). |
1032 |
1098 |
1033 To explain how to write your own attribute, let us start with an extremely simple |
1099 To explain how to write your own attribute, let us start with an extremely simple |
1034 version of the attribute @{text "[symmetric]"}. The purpose of this attribute is |
1100 version of the attribute @{text "[symmetric]"}. The purpose of this attribute is |
1035 to produce the ``symmetric'' version of an equation. The main function behind |
1101 to produce the ``symmetric'' version of an equation. The main function behind |
1036 this attribute is |
1102 this attribute is |
1044 returns another theorem (namely @{text thm} resolved with the lemma |
1110 returns another theorem (namely @{text thm} resolved with the lemma |
1045 @{thm [source] sym}: @{thm sym[no_vars]}). The function @{ML "Thm.rule_attribute"} then returns |
1111 @{thm [source] sym}: @{thm sym[no_vars]}). The function @{ML "Thm.rule_attribute"} then returns |
1046 an attribute. |
1112 an attribute. |
1047 |
1113 |
1048 Before we can use the attribute, we need to set it up. This can be done |
1114 Before we can use the attribute, we need to set it up. This can be done |
1049 using the function @{ML Attrib.setup} as follows. |
1115 using the Isabelle command \isacommand{attribute\_setup} as follows: |
1050 *} |
1116 *} |
1051 |
1117 |
1052 setup %gray {* Attrib.setup @{binding "my_sym"} |
1118 attribute_setup %gray my_sym = {* Scan.succeed my_symmetric *} |
1053 (Scan.succeed my_symmetric) "applying the sym rule"*} |
1119 "applying the sym rule" |
1054 |
1120 |
1055 text {* |
1121 text {* |
1056 The attribute does not expect any further arguments (unlike @{text "[OF |
1122 The attribute does not expect any further arguments (unlike @{text "[THEN |
1057 \<dots>]"}, for example, which can take a list of theorems as argument). Therefore |
1123 \<dots>]"}, for example). Therefore |
1058 we use the parser @{ML Scan.succeed}. Later on we will also consider |
1124 we use the parser @{ML Scan.succeed}. Later on we will also consider |
1059 attributes taking further arguments. An example for the attribute @{text |
1125 attributes taking further arguments. An example for the attribute @{text |
1060 "[my_sym]"} is the proof |
1126 "[my_sym]"} is the proof |
1061 *} |
1127 *} |
1062 |
1128 |
1063 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp |
1129 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp |
1064 |
1130 |
1065 text {* |
1131 text {* |
1066 which stores the theorem @{thm test} under the name @{thm [source] test}. We |
1132 which stores the theorem @{thm test} under the name @{thm [source] test}. You |
1067 can also use the attribute when referring to this theorem. |
1133 can see this, if you query the lemma: |
|
1134 |
|
1135 \begin{isabelle} |
|
1136 \isacommand{thm}~@{text "test"}\\ |
|
1137 @{text "> "}~@{thm test} |
|
1138 \end{isabelle} |
|
1139 |
|
1140 We can also use the attribute when referring to this theorem: |
1068 |
1141 |
1069 \begin{isabelle} |
1142 \begin{isabelle} |
1070 \isacommand{thm}~@{text "test[my_sym]"}\\ |
1143 \isacommand{thm}~@{text "test[my_sym]"}\\ |
1071 @{text "> "}~@{thm test[my_sym]} |
1144 @{text "> "}~@{thm test[my_sym]} |
1072 \end{isabelle} |
1145 \end{isabelle} |
|
1146 |
|
1147 As an example of a slightly more complicated theorem attribute, we implement |
|
1148 our version of @{text "[THEN \<dots>]"}. This attribute takes a list of theorems |
|
1149 as argument and resolves the proved theorem with this list (one theorem |
|
1150 after another). The code for this attribute is: |
|
1151 *} |
|
1152 |
|
1153 ML{*fun MY_THEN thms = |
|
1154 Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*} |
|
1155 |
|
1156 text {* |
|
1157 where @{ML swap} swaps the components of a pair. The setup of this theorem |
|
1158 attribute uses the parser @{ML Attrib.thms}, which parses a list of |
|
1159 theorems. |
|
1160 *} |
|
1161 |
|
1162 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} |
|
1163 "resolving the list of theorems with the proved theorem" |
|
1164 |
|
1165 text {* |
|
1166 You can, for example, use this theorem attribute to turn an equation into a |
|
1167 meta-equation: |
|
1168 |
|
1169 \begin{isabelle} |
|
1170 \isacommand{thm}~@{text "test[MY_THEN eq_reflection]"}\\ |
|
1171 @{text "> "}~@{thm test[MY_THEN eq_reflection]} |
|
1172 \end{isabelle} |
|
1173 |
|
1174 If you need the symmetric version as a meta-equation, you can write |
|
1175 |
|
1176 \begin{isabelle} |
|
1177 \isacommand{thm}~@{text "test[MY_THEN sym eq_reflection]"}\\ |
|
1178 @{text "> "}~@{thm test[MY_THEN sym eq_reflection]} |
|
1179 \end{isabelle} |
|
1180 |
|
1181 Of course, it is also possible to combine different theorem attributes, as in: |
|
1182 |
|
1183 \begin{isabelle} |
|
1184 \isacommand{thm}~@{text "test[my_sym, MY_THEN eq_reflection]"}\\ |
|
1185 @{text "> "}~@{thm test[my_sym, MY_THEN eq_reflection]} |
|
1186 \end{isabelle} |
|
1187 |
|
1188 However, here also a weakness of the concept |
|
1189 of theorem attributes show through: since theorem attributes can be an |
|
1190 arbitrary functions, they do not in general commute. If you try |
|
1191 |
|
1192 \begin{isabelle} |
|
1193 \isacommand{thm}~@{text "test[MY_THEN eq_reflection, my_sym]"}\\ |
|
1194 @{text "> "}~@{text "exception THM 1 raised: RSN: no unifiers"} |
|
1195 \end{isabelle} |
|
1196 |
|
1197 you get an exception indicating that the theorem @{thm [source] sym} |
|
1198 does not resolve with meta-equations. |
1073 |
1199 |
1074 The purpose of @{ML Thm.rule_attribute} is to directly manipulate theorems. |
1200 The purpose of @{ML Thm.rule_attribute} is to directly manipulate theorems. |
1075 Another usage of attributes is to add and delete theorems from stored data. |
1201 Another usage of attributes is to add and delete theorems from stored data. |
1076 For example the attribute @{text "[simp]"} adds or deletes a theorem from the |
1202 For example the attribute @{text "[simp]"} adds or deletes a theorem from the |
1077 current simpset. For these applications, you can use @{ML Thm.declaration_attribute}. |
1203 current simpset. For these applications, you can use @{ML Thm.declaration_attribute}. |
1078 To illustrate this function, let us introduce a reference containing a list |
1204 To illustrate this function, let us introduce a reference containing a list |
1079 of theorems. |
1205 of theorems. |
1080 *} |
1206 *} |
1081 |
1207 |
1082 ML{*val my_thms = ref ([]:thm list)*} |
1208 ML{*val my_thms = ref ([] : thm list)*} |
1083 |
1209 |
1084 text {* |
1210 text {* |
1085 A word of warning: such references must not be used in any code that |
1211 A word of warning: such references must not be used in any code that |
1086 is meant to be more than just for testing purposes! Here it is only used |
1212 is meant to be more than just for testing purposes! Here it is only used |
1087 to illustrate matters. We will show later how to store data properly without |
1213 to illustrate matters. We will show later how to store data properly without |
1088 using references. The function @{ML Thm.declaration_attribute} expects us to |
1214 using references. |
|
1215 |
|
1216 The function @{ML Thm.declaration_attribute} expects us to |
1089 provide two functions that add and delete theorems from this list. |
1217 provide two functions that add and delete theorems from this list. |
1090 For this we use the two functions: |
1218 For this we use the two functions: |
1091 *} |
1219 *} |
1092 |
1220 |
1093 ML{*fun my_thms_add thm ctxt = |
1221 ML{*fun my_thms_add thm ctxt = |
1165 However, as said at the beginning of this example, using references for storing theorems is |
1293 However, as said at the beginning of this example, using references for storing theorems is |
1166 \emph{not} the received way of doing such things. The received way is to |
1294 \emph{not} the received way of doing such things. The received way is to |
1167 start a ``data slot'' in a context by using the functor @{text GenericDataFun}: |
1295 start a ``data slot'' in a context by using the functor @{text GenericDataFun}: |
1168 *} |
1296 *} |
1169 |
1297 |
1170 ML {*structure Data = GenericDataFun |
1298 ML {*structure MyThmsData = GenericDataFun |
1171 (type T = thm list |
1299 (type T = thm list |
1172 val empty = [] |
1300 val empty = [] |
1173 val extend = I |
1301 val extend = I |
1174 fun merge _ = Thm.merge_thms) *} |
1302 fun merge _ = Thm.merge_thms) *} |
1175 |
1303 |
1176 text {* |
1304 text {* |
1177 To use this data slot, you only have to change @{ML my_thms_add} and |
1305 To use this data slot, you only have to change @{ML my_thms_add} and |
1178 @{ML my_thms_del} to: |
1306 @{ML my_thms_del} to: |
1179 *} |
1307 *} |
1180 |
1308 |
1181 ML{*val thm_add = Data.map o Thm.add_thm |
1309 ML{*val thm_add = MyThmsData.map o Thm.add_thm |
1182 val thm_del = Data.map o Thm.del_thm*} |
1310 val thm_del = MyThmsData.map o Thm.del_thm*} |
1183 |
1311 |
1184 text {* |
1312 text {* |
1185 where @{ML Data.map} updates the data appropriately in the context. Since storing |
1313 where @{ML MyThmsData.map} updates the data appropriately in the context. The |
|
1314 theorem addtributes are |
|
1315 *} |
|
1316 |
|
1317 ML{*val add = Thm.declaration_attribute thm_add |
|
1318 val del = Thm.declaration_attribute thm_del *} |
|
1319 |
|
1320 text {* |
|
1321 ad the setup is as follows |
|
1322 *} |
|
1323 |
|
1324 attribute_setup %gray my_thms2 = {* Attrib.add_del add del *} |
|
1325 "properly maintaining a list of my_thms" |
|
1326 |
|
1327 ML {* MyThmsData.get (Context.Proof @{context}) *} |
|
1328 |
|
1329 lemma [my_thms2]: "2 = Suc (Suc 0)" by simp |
|
1330 |
|
1331 ML {* MyThmsData.get (Context.Proof @{context}) *} |
|
1332 |
|
1333 ML {* !my_thms *} |
|
1334 |
|
1335 text {* |
|
1336 (FIXME: explain problem with backtracking) |
|
1337 |
|
1338 Since storing |
1186 theorems in a special list is such a common task, there is the functor @{text NamedThmsFun}, |
1339 theorems in a special list is such a common task, there is the functor @{text NamedThmsFun}, |
1187 which does most of the work for you. To obtain such a named theorem lists, you just |
1340 which does most of the work for you. To obtain such a named theorem lists, you just |
1188 declare |
1341 declare |
1189 *} |
1342 *} |
1190 |
1343 |