ProgTutorial/FirstSteps.thy
changeset 194 8cd51a25a7ca
parent 193 ffd93dcc269d
child 204 3857d987576a
equal deleted inserted replaced
193:ffd93dcc269d 194:8cd51a25a7ca
   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
   657 *}
   658 *}
   658 
   659 
   659 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *}
   660 ML{*fun make_wrong_imp P Q = @{prop "\<And>(x::nat). P x \<Longrightarrow> Q x"} *}
   660 
   661 
   661 text {*
   662 text {*
   662   To see this apply @{text "@{term S}"} and @{text "@{term T}"} 
   663   To see this, apply @{text "@{term S}"} and @{text "@{term T}"} 
   663   to both functions. With @{ML make_imp} you obtain the intended term involving 
   664   to both functions. With @{ML make_imp} you obtain the intended term involving 
   664   the given arguments
   665   the given arguments
   665 
   666 
   666   @{ML_response [display,gray] "make_imp @{term S} @{term T}" 
   667   @{ML_response [display,gray] "make_imp @{term S} @{term T}" 
   667 "Const \<dots> $ 
   668 "Const \<dots> $ 
   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