178 text {* |
178 text {* |
179 The easiest way to get the string of a theorem is to transform it |
179 The easiest way to get the string of a theorem is to transform it |
180 into a @{ML_type cterm} using the function @{ML crep_thm}. |
180 into a @{ML_type cterm} using the function @{ML crep_thm}. |
181 *} |
181 *} |
182 |
182 |
183 ML{*fun str_of_thm_raw ctxt thm = |
183 ML{*fun str_of_thm ctxt thm = |
184 str_of_cterm ctxt (#prop (crep_thm thm))*} |
184 str_of_cterm ctxt (#prop (crep_thm thm))*} |
185 |
185 |
186 text {* |
186 text {* |
187 Theorems also include schematic variables, such as @{text "?P"}, |
187 Theorems also include schematic variables, such as @{text "?P"}, |
188 @{text "?Q"} and so on. |
188 @{text "?Q"} and so on. |
189 |
189 |
190 @{ML_response_fake [display, gray] |
190 @{ML_response_fake [display, gray] |
191 "warning (str_of_thm_raw @{context} @{thm conjI})" |
191 "warning (str_of_thm @{context} @{thm conjI})" |
192 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
192 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
193 |
193 |
194 In order to improve the readability of theorems we convert |
194 In order to improve the readability of theorems we convert |
195 these schematic variables into free variables using the |
195 these schematic variables into free variables using the |
196 function @{ML Variable.import_thms}. |
196 function @{ML Variable.import_thms}. |
201 val ((_, [thm']), _) = Variable.import_thms true [thm] ctxt |
201 val ((_, [thm']), _) = Variable.import_thms true [thm] ctxt |
202 in |
202 in |
203 thm' |
203 thm' |
204 end |
204 end |
205 |
205 |
206 fun str_of_thm ctxt thm = |
206 fun str_of_thm_no_vars ctxt thm = |
207 str_of_cterm ctxt (#prop (crep_thm (no_vars ctxt thm)))*} |
207 str_of_cterm ctxt (#prop (crep_thm (no_vars ctxt thm)))*} |
208 |
208 |
209 text {* |
209 text {* |
210 Theorem @{thm [source] conjI} looks now as follows |
210 Theorem @{thm [source] conjI} looks now as follows: |
211 |
211 |
212 @{ML_response_fake [display, gray] |
212 @{ML_response_fake [display, gray] |
213 "warning (str_of_thm_raw @{context} @{thm conjI})" |
213 "warning (str_of_thm_no_vars @{context} @{thm conjI})" |
214 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
214 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
215 |
215 |
216 Again the function @{ML commas} helps with printing more than one theorem. |
216 Again the function @{ML commas} helps with printing more than one theorem. |
217 *} |
217 *} |
218 |
218 |
219 ML{*fun str_of_thms ctxt thms = |
219 ML{*fun str_of_thms ctxt thms = |
220 commas (map (str_of_thm ctxt) thms) |
220 commas (map (str_of_thm ctxt) thms) |
221 |
221 |
222 fun str_of_thms_raw ctxt thms = |
222 fun str_of_thms_no_vars ctxt thms = |
223 commas (map (str_of_thm_raw ctxt) thms)*} |
223 commas (map (str_of_thm_no_vars ctxt) thms) *} |
224 |
224 |
225 section {* Combinators\label{sec:combinators} *} |
225 section {* Combinators\label{sec:combinators} *} |
226 |
226 |
227 text {* |
227 text {* |
228 For beginners perhaps the most puzzling parts in the existing code of Isabelle are |
228 For beginners perhaps the most puzzling parts in the existing code of Isabelle are |
303 |> Variable.variant_frees ctxt [f] |
303 |> Variable.variant_frees ctxt [f] |
304 |> map Free |
304 |> map Free |
305 |> (curry list_comb) f *} |
305 |> (curry list_comb) f *} |
306 |
306 |
307 text {* |
307 text {* |
308 This code extracts the argument types of a given function and then generates |
308 This code extracts the argument types of a given function @{text "f"} and then generates |
309 for each argument type a distinct variable; finally it applies the generated |
309 for each argument type a distinct variable; finally it applies the generated |
310 variables to the function. For example |
310 variables to the function. For example: |
311 |
311 |
312 @{ML_response_fake [display,gray] |
312 @{ML_response_fake [display,gray] |
313 "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} |
314 |> Syntax.string_of_term @{context} |
314 |> Syntax.string_of_term @{context} |
315 |> warning" |
315 |> warning" |
321 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 |
322 pairs up each type with the string @{text "z"}; the |
322 pairs up each type with the string @{text "z"}; the |
323 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 |
324 unique name avoiding the given @{text f}; the list of name-type pairs is turned |
324 unique name avoiding the given @{text f}; the list of name-type pairs is turned |
325 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 |
326 by the function @{ML list_comb} to the function. We have to use the |
326 by the function @{ML list_comb} to the function. In this last step we have to |
327 function @{ML curry}, because @{ML list_comb} expects the function and the |
327 use the function @{ML curry}, because @{ML list_comb} expects the function and the |
328 variables list as a pair. |
328 variables list as a pair. |
329 |
329 |
330 The combinator @{ML "#>"} is the reverse function composition. It can be |
330 The combinator @{ML "#>"} is the reverse function composition. It can be |
331 used to define the following function |
331 used to define the following function |
332 *} |
332 *} |
523 \begin{isabelle} |
523 \begin{isabelle} |
524 \isacommand{thm}~@{text "TrueConj_def"}\\ |
524 \isacommand{thm}~@{text "TrueConj_def"}\\ |
525 @{text "> "}@{thm TrueConj_def} |
525 @{text "> "}@{thm TrueConj_def} |
526 \end{isabelle} |
526 \end{isabelle} |
527 |
527 |
528 (FIXME give a better example why bindings are important) |
528 (FIXME give a better example why bindings are important; maybe |
|
529 give a pointer to \isacommand{local\_setup}) |
529 |
530 |
530 While antiquotations have many applications, they were originally introduced in order |
531 While antiquotations have many applications, they were originally introduced in order |
531 to avoid explicit bindings for theorems such as: |
532 to avoid explicit bindings for theorems such as: |
532 *} |
533 *} |
533 |
534 |
576 |
577 |
577 @{ML_response_fake_both [display,gray] |
578 @{ML_response_fake_both [display,gray] |
578 "@{term \"(x::nat) x\"}" |
579 "@{term \"(x::nat) x\"}" |
579 "Type unification failed \<dots>"} |
580 "Type unification failed \<dots>"} |
580 |
581 |
581 raises a typing error, while it perfectly ok to construct |
582 raises a typing error, while it perfectly ok to construct the term |
582 |
583 |
583 @{ML [display,gray] "Free (\"x\", @{typ nat}) $ Free (\"x\", @{typ nat})"} |
584 @{ML [display,gray] "Free (\"x\", @{typ nat}) $ Free (\"x\", @{typ nat})"} |
584 |
585 |
585 with the raw ML-constructors. |
586 with the raw ML-constructors. |
586 Sometimes the internal representation of terms can be surprisingly different |
587 Sometimes the internal representation of terms can be surprisingly different |
677 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
678 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
678 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
679 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
679 |
680 |
680 There are a number of handy functions that are frequently used for |
681 There are a number of handy functions that are frequently used for |
681 constructing terms. One is the function @{ML list_comb}, which takes |
682 constructing terms. One is the function @{ML list_comb}, which takes |
682 a term and a list of terms as argument, and produces as output the term |
683 a term and a list of terms as arguments, and produces as output the term |
683 list applied to the term. For example |
684 list applied to the term. For example |
684 |
685 |
685 @{ML_response_fake [display,gray] |
686 @{ML_response_fake [display,gray] |
686 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])" |
687 "list_comb (@{term \"P::nat\"}, [@{term \"True\"}, @{term \"False\"}])" |
687 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
688 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
691 |
692 |
692 @{ML_response_fake [display,gray] |
693 @{ML_response_fake [display,gray] |
693 "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}" |
694 "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}" |
694 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
695 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
695 |
696 |
696 In the example @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
697 In the example, @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
697 and an abstraction. It also records the type of the abstracted |
698 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 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 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 is of the same type as the abstracted variable. If it is of different type, |
701 as in |
702 as in |
708 This is a fundamental principle |
709 This is a fundamental principle |
709 of Church-style typing, where variables with the same name still differ, if they |
710 of Church-style typing, where variables with the same name still differ, if they |
710 have different type. |
711 have different type. |
711 |
712 |
712 There is also the function @{ML subst_free} with which terms can |
713 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 be replaced by other terms. For example below, we will replace in |
714 the subterm @{term "f 0"} by @{term y} and @{term x} by @{term True}. |
715 @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0 x"} |
|
716 the subterm @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0"} by @{term y}, and @{term x} by @{term True}. |
715 |
717 |
716 @{ML_response_fake [display,gray] |
718 @{ML_response_fake [display,gray] |
717 "subst_free [(@{term \"(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0\"}, @{term \"y::nat\<Rightarrow>nat\"}), |
719 "subst_free [(@{term \"(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0\"}, @{term \"y::nat\<Rightarrow>nat\"}), |
718 (@{term \"x::nat\"}, @{term \"True\"})] |
720 (@{term \"x::nat\"}, @{term \"True\"})] |
719 @{term \"((f::nat\<Rightarrow>nat\<Rightarrow>nat) 0) x\"}" |
721 @{term \"((f::nat\<Rightarrow>nat\<Rightarrow>nat) 0) x\"}" |
1064 For the functions @{text "assume"}, @{text "forall_elim"} etc |
1066 For the functions @{text "assume"}, @{text "forall_elim"} etc |
1065 see \isccite{sec:thms}. The basic functions for theorems are defined in |
1067 see \isccite{sec:thms}. The basic functions for theorems are defined in |
1066 @{ML_file "Pure/thm.ML"}. |
1068 @{ML_file "Pure/thm.ML"}. |
1067 \end{readmore} |
1069 \end{readmore} |
1068 |
1070 |
1069 (FIXME: how to add case-names to goal states - maybe in the next section) |
1071 (FIXME: handy functions working on theorems; how to add case-names to goal |
|
1072 states - maybe in the next section) |
1070 *} |
1073 *} |
1071 |
1074 |
1072 section {* Theorem Attributes *} |
1075 section {* Theorem Attributes *} |
1073 |
1076 |
1074 text {* |
1077 text {* |
1143 \isacommand{thm}~@{text "test[my_sym]"}\\ |
1146 \isacommand{thm}~@{text "test[my_sym]"}\\ |
1144 @{text "> "}~@{thm test[my_sym]} |
1147 @{text "> "}~@{thm test[my_sym]} |
1145 \end{isabelle} |
1148 \end{isabelle} |
1146 |
1149 |
1147 As an example of a slightly more complicated theorem attribute, we implement |
1150 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 |
1151 our version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems |
1149 as argument and resolves the proved theorem with this list (one theorem |
1152 as argument and resolve the proved theorem with this list (one theorem |
1150 after another). The code for this attribute is: |
1153 after another). The code for this attribute is |
1151 *} |
1154 *} |
1152 |
1155 |
1153 ML{*fun MY_THEN thms = |
1156 ML{*fun MY_THEN thms = |
1154 Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*} |
1157 Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*} |
1155 |
1158 |
1156 text {* |
1159 text {* |
1157 where @{ML swap} swaps the components of a pair. The setup of this theorem |
1160 where @{ML swap} swaps the components of a pair (@{ML RS} is explained |
|
1161 later on in Section~\ref{sec:simpletacs}). The setup of this theorem |
1158 attribute uses the parser @{ML Attrib.thms}, which parses a list of |
1162 attribute uses the parser @{ML Attrib.thms}, which parses a list of |
1159 theorems. |
1163 theorems. |
1160 *} |
1164 *} |
1161 |
1165 |
1162 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} |
1166 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} |
1176 \begin{isabelle} |
1180 \begin{isabelle} |
1177 \isacommand{thm}~@{text "test[MY_THEN sym eq_reflection]"}\\ |
1181 \isacommand{thm}~@{text "test[MY_THEN sym eq_reflection]"}\\ |
1178 @{text "> "}~@{thm test[MY_THEN sym eq_reflection]} |
1182 @{text "> "}~@{thm test[MY_THEN sym eq_reflection]} |
1179 \end{isabelle} |
1183 \end{isabelle} |
1180 |
1184 |
1181 Of course, it is also possible to combine different theorem attributes, as in: |
1185 It is also possible to combine different theorem attributes, as in: |
1182 |
1186 |
1183 \begin{isabelle} |
1187 \begin{isabelle} |
1184 \isacommand{thm}~@{text "test[my_sym, MY_THEN eq_reflection]"}\\ |
1188 \isacommand{thm}~@{text "test[my_sym, MY_THEN eq_reflection]"}\\ |
1185 @{text "> "}~@{thm test[my_sym, MY_THEN eq_reflection]} |
1189 @{text "> "}~@{thm test[my_sym, MY_THEN eq_reflection]} |
1186 \end{isabelle} |
1190 \end{isabelle} |
1187 |
1191 |
1188 However, here also a weakness of the concept |
1192 However, here also a weakness of the concept |
1189 of theorem attributes show through: since theorem attributes can be an |
1193 of theorem attributes shows through: since theorem attributes can be |
1190 arbitrary functions, they do not in general commute. If you try |
1194 arbitrary functions, they do not in general commute. If you try |
1191 |
1195 |
1192 \begin{isabelle} |
1196 \begin{isabelle} |
1193 \isacommand{thm}~@{text "test[MY_THEN eq_reflection, my_sym]"}\\ |
1197 \isacommand{thm}~@{text "test[MY_THEN eq_reflection, my_sym]"}\\ |
1194 @{text "> "}~@{text "exception THM 1 raised: RSN: no unifiers"} |
1198 @{text "> "}~@{text "exception THM 1 raised: RSN: no unifiers"} |
1196 |
1200 |
1197 you get an exception indicating that the theorem @{thm [source] sym} |
1201 you get an exception indicating that the theorem @{thm [source] sym} |
1198 does not resolve with meta-equations. |
1202 does not resolve with meta-equations. |
1199 |
1203 |
1200 The purpose of @{ML Thm.rule_attribute} is to directly manipulate theorems. |
1204 The purpose of @{ML Thm.rule_attribute} is to directly manipulate theorems. |
1201 Another usage of attributes is to add and delete theorems from stored data. |
1205 Another usage of theorem attributes is to add and delete theorems from stored data. |
1202 For example the attribute @{text "[simp]"} adds or deletes a theorem from the |
1206 For example the theorem attribute @{text "[simp]"} adds or deletes a theorem from the |
1203 current simpset. For these applications, you can use @{ML Thm.declaration_attribute}. |
1207 current simpset. For these applications, you can use @{ML Thm.declaration_attribute}. |
1204 To illustrate this function, let us introduce a reference containing a list |
1208 To illustrate this function, let us introduce a reference containing a list |
1205 of theorems. |
1209 of theorems. |
1206 *} |
1210 *} |
1207 |
1211 |
1227 text {* |
1231 text {* |
1228 These functions take a theorem and a context and, for what we are explaining |
1232 These functions take a theorem and a context and, for what we are explaining |
1229 here it is sufficient that they just return the context unchanged. They change |
1233 here it is sufficient that they just return the context unchanged. They change |
1230 however the reference @{ML my_thms}, whereby the function @{ML Thm.add_thm} |
1234 however the reference @{ML my_thms}, whereby the function @{ML Thm.add_thm} |
1231 adds a theorem if it is not already included in the list, and @{ML |
1235 adds a theorem if it is not already included in the list, and @{ML |
1232 Thm.del_thm} deletes one. Both functions use the predicate @{ML |
1236 Thm.del_thm} deletes one (both functions use the predicate @{ML |
1233 Thm.eq_thm_prop} which compares theorems according to their proved |
1237 Thm.eq_thm_prop}, which compares theorems according to their proved |
1234 propositions (modulo alpha-equivalence). |
1238 propositions modulo alpha-equivalence). |
1235 |
1239 |
1236 |
1240 |
1237 You can turn both functions into attributes using |
1241 You can turn functions @{ML my_thms_add} and @{ML my_thms_del} into |
|
1242 attributes with the code |
1238 *} |
1243 *} |
1239 |
1244 |
1240 ML{*val my_add = Thm.declaration_attribute my_thms_add |
1245 ML{*val my_add = Thm.declaration_attribute my_thms_add |
1241 val my_del = Thm.declaration_attribute my_thms_del *} |
1246 val my_del = Thm.declaration_attribute my_thms_del *} |
1242 |
1247 |
1246 |
1251 |
1247 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} |
1252 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} |
1248 "maintaining a list of my_thms" |
1253 "maintaining a list of my_thms" |
1249 |
1254 |
1250 text {* |
1255 text {* |
1251 Now if you prove the lemma attaching the attribute @{text "[my_thms]"} |
1256 The parser @{ML Attrib.add_del} is a predefined parser for |
|
1257 adding and deleting lemmas. Now if you prove the next lemma |
|
1258 and attach the attribute |
|
1259 @{text "[my_thms]"} |
1252 *} |
1260 *} |
1253 |
1261 |
1254 lemma trueI_2[my_thms]: "True" by simp |
1262 lemma trueI_2[my_thms]: "True" by simp |
1255 |
1263 |
1256 text {* |
1264 text {* |
1257 then you can see the lemma is added to the initially empty list. |
1265 then you can see it is added to the initially empty list. |
1258 |
1266 |
1259 @{ML_response_fake [display,gray] |
1267 @{ML_response_fake [display,gray] |
1260 "!my_thms" "[\"True\"]"} |
1268 "!my_thms" "[\"True\"]"} |
1261 |
1269 |
1262 You can also add theorems using the command \isacommand{declare}. |
1270 You can also add theorems using the command \isacommand{declare}. |
1264 |
1272 |
1265 declare test[my_thms] trueI_2[my_thms add] |
1273 declare test[my_thms] trueI_2[my_thms add] |
1266 |
1274 |
1267 text {* |
1275 text {* |
1268 The @{text "add"} is the default operation and does not need |
1276 The @{text "add"} is the default operation and does not need |
1269 to be given. This declaration will cause the theorem list to be |
1277 to be explicitly given. These two declarations will cause the |
1270 updated as follows. |
1278 theorem list to be updated as: |
1271 |
1279 |
1272 @{ML_response_fake [display,gray] |
1280 @{ML_response_fake [display,gray] |
1273 "!my_thms" |
1281 "!my_thms" |
1274 "[\"True\", \"Suc (Suc 0) = 2\"]"} |
1282 "[\"True\", \"Suc (Suc 0) = 2\"]"} |
1275 |
1283 |
1290 but there can be any number of them. We just have to change the parser for reading |
1298 but there can be any number of them. We just have to change the parser for reading |
1291 the arguments accordingly. |
1299 the arguments accordingly. |
1292 |
1300 |
1293 However, as said at the beginning of this example, using references for storing theorems is |
1301 However, as said at the beginning of this example, using references for storing theorems is |
1294 \emph{not} the received way of doing such things. The received way is to |
1302 \emph{not} the received way of doing such things. The received way is to |
1295 start a ``data slot'' in a context by using the functor @{text GenericDataFun}: |
1303 start a ``data slot'', below called @{text MyThmsData}, by using the functor |
|
1304 @{text GenericDataFun}: |
1296 *} |
1305 *} |
1297 |
1306 |
1298 ML {*structure MyThmsData = GenericDataFun |
1307 ML {*structure MyThmsData = GenericDataFun |
1299 (type T = thm list |
1308 (type T = thm list |
1300 val empty = [] |
1309 val empty = [] |
1308 |
1317 |
1309 ML{*val thm_add = MyThmsData.map o Thm.add_thm |
1318 ML{*val thm_add = MyThmsData.map o Thm.add_thm |
1310 val thm_del = MyThmsData.map o Thm.del_thm*} |
1319 val thm_del = MyThmsData.map o Thm.del_thm*} |
1311 |
1320 |
1312 text {* |
1321 text {* |
1313 where @{ML MyThmsData.map} updates the data appropriately in the context. The |
1322 where @{ML MyThmsData.map} updates the data appropriately. The |
1314 theorem addtributes are |
1323 corresponding theorem addtributes are |
1315 *} |
1324 *} |
1316 |
1325 |
1317 ML{*val add = Thm.declaration_attribute thm_add |
1326 ML{*val add = Thm.declaration_attribute thm_add |
1318 val del = Thm.declaration_attribute thm_del *} |
1327 val del = Thm.declaration_attribute thm_del *} |
1319 |
1328 |
1320 text {* |
1329 text {* |
1321 ad the setup is as follows |
1330 and the setup is as follows |
1322 *} |
1331 *} |
1323 |
1332 |
1324 attribute_setup %gray my_thms2 = {* Attrib.add_del add del *} |
1333 attribute_setup %gray my_thms2 = {* Attrib.add_del add del *} |
1325 "properly maintaining a list of my_thms" |
1334 "properly maintaining a list of my_thms" |
1326 |
1335 |
1327 ML {* MyThmsData.get (Context.Proof @{context}) *} |
1336 text {* |
1328 |
1337 Initially, the data slot is empty |
1329 lemma [my_thms2]: "2 = Suc (Suc 0)" by simp |
1338 |
1330 |
1339 @{ML_response_fake [display,gray] |
1331 ML {* MyThmsData.get (Context.Proof @{context}) *} |
1340 "MyThmsData.get (Context.Proof @{context})" |
1332 |
1341 "[]"} |
1333 ML {* !my_thms *} |
1342 |
1334 |
1343 but if you prove |
1335 text {* |
1344 *} |
1336 (FIXME: explain problem with backtracking) |
1345 |
1337 |
1346 lemma three[my_thms2]: "3 = Suc (Suc (Suc 0))" by simp |
1338 Since storing |
1347 |
1339 theorems in a special list is such a common task, there is the functor @{text NamedThmsFun}, |
1348 text {* |
1340 which does most of the work for you. To obtain such a named theorem lists, you just |
1349 the lemma is now included |
1341 declare |
1350 |
|
1351 @{ML_response_fake [display,gray] |
|
1352 "MyThmsData.get (Context.Proof @{context})" |
|
1353 "[\"3 = Suc (Suc (Suc 0))\"]"} |
|
1354 |
|
1355 With @{text my_thms2} you can also nicely see why it is important to |
|
1356 store data in a ``data slot'' and \emph{not} in a reference. Backtrack |
|
1357 to the point just before the lemma @{thm [source] three} is proved and |
|
1358 check the the content of @{ML_struct "MyThmsData"}: it is now again |
|
1359 empty. The addition has been properly retracted. Now consider the proof: |
|
1360 *} |
|
1361 |
|
1362 lemma four[my_thms]: "4 = Suc (Suc (Suc (Suc 0)))" by simp |
|
1363 |
|
1364 text {* |
|
1365 Checking the content of @{ML my_thms} gives |
|
1366 |
|
1367 @{ML_response_fake [display,gray] |
|
1368 "!my_thms" |
|
1369 "[\"4 = Suc (Suc (Suc (Suc 0)))\", \"True\"]"} |
|
1370 |
|
1371 as expected, but if we backtrack before the lemma @{thm [source] four}, the |
|
1372 content of @{ML my_thms} is unchanged. The backtracking mechanism |
|
1373 of Isabelle is completely oblivious about what to do with references! |
|
1374 |
|
1375 Since storing theorems in a special list is such a common task, there is the |
|
1376 functor @{text NamedThmsFun}, which does most of the work for you. To obtain |
|
1377 such a named theorem lists, you just declare |
1342 *} |
1378 *} |
1343 |
1379 |
1344 ML{*structure FooRules = NamedThmsFun |
1380 ML{*structure FooRules = NamedThmsFun |
1345 (val name = "foo" |
1381 (val name = "foo" |
1346 val description = "Rules for foo"); *} |
1382 val description = "Rules for foo") *} |
1347 |
1383 |
1348 text {* |
1384 text {* |
1349 and set up the @{ML_struct FooRules} with the command |
1385 and set up the @{ML_struct FooRules} with the command |
1350 *} |
1386 *} |
1351 |
1387 |