ProgTutorial/General.thy
changeset 353 e73ccbed776e
parent 352 9f12e53eb121
child 354 544c149005cf
equal deleted inserted replaced
352:9f12e53eb121 353:e73ccbed776e
   596   \end{tabular}
   596   \end{tabular}
   597   \end{center}
   597   \end{center}
   598 
   598 
   599   Make sure you use the functions defined in @{ML_file "HOL/Tools/hologic.ML"}
   599   Make sure you use the functions defined in @{ML_file "HOL/Tools/hologic.ML"}
   600   for constructing the terms for the logical connectives.\footnote{Thanks to Roy
   600   for constructing the terms for the logical connectives.\footnote{Thanks to Roy
   601   Dyckhoff for this exercise.} 
   601   Dyckhoff for suggesting this exercise and working out the details.} 
   602   \end{exercise}
   602   \end{exercise}
   603 *}
   603 *}
   604 
   604 
   605 
   605 
   606 section {* Type-Checking\label{sec:typechecking} *}
   606 section {* Type-Checking\label{sec:typechecking} *}
   823 
   823 
   824   While we obtained a theorem as result, this theorem is not
   824   While we obtained a theorem as result, this theorem is not
   825   yet stored in Isabelle's theorem database. Consequently, it cannot be 
   825   yet stored in Isabelle's theorem database. Consequently, it cannot be 
   826   referenced on the user level. One way to store it in the theorem database is
   826   referenced on the user level. One way to store it in the theorem database is
   827   by using the function @{ML_ind note in LocalTheory}.\footnote{\bf FIXME: make sure a pointer
   827   by using the function @{ML_ind note in LocalTheory}.\footnote{\bf FIXME: make sure a pointer
   828   to the section about local-setup is given eralier.}
   828   to the section about local-setup is given earlier.}
   829 *}
   829 *}
   830 
   830 
   831 local_setup %gray {*
   831 local_setup %gray {*
   832   LocalTheory.note Thm.theoremK
   832   LocalTheory.note Thm.theoremK
   833      ((@{binding "my_thm"}, []), [my_thm]) #> snd *}
   833      ((@{binding "my_thm"}, []), [my_thm]) #> snd *}
   834 
   834 
   835 text {*
   835 text {*
   836   The first argument @{ML_ind theoremK in Thm} is a kind indicator, which
   836   The fourth argument of @{ML note in LocalTheory} is the list of theorems we
   837   classifies the theorem. There are several such kind indicators: for a
   837   want to store under a name.  The first argument @{ML_ind theoremK in Thm} is
   838   theorem arising from a definition we should use @{ML_ind definitionK in
   838   a kind indicator, which classifies the theorem. There are several such kind
   839   Thm}, for an axiom @{ML_ind axiomK in Thm}, and for ``normal'' theorems the
   839   indicators: for a theorem arising from a definition you should use @{ML_ind
   840   kinds @{ML_ind theoremK in Thm} or @{ML_ind lemmaK in Thm}.  The second
   840   definitionK in Thm}, for an axiom @{ML_ind axiomK in Thm}, and for
   841   argument of @{ML note in LocalTheory} is the name under which we store the
   841   ``normal'' theorems the kinds @{ML_ind theoremK in Thm} or @{ML_ind lemmaK
   842   theorem or theorems. The third argument can contain a list of theorem
   842   in Thm}.  The second argument of @{ML note in LocalTheory} is the name under
   843   attributes, which we will explain in detail in Section~\ref{sec:attributes}. 
   843   which we store the theorem or theorems. The third argument can contain a
   844   Below we just use one such attribute in order add
   844   list of theorem attributes, which we will explain in detail in
   845   the theorem to the simpset:
   845   Section~\ref{sec:attributes}. Below we just use one such attribute in order
       
   846   add the theorem to the simpset:
   846 *}
   847 *}
   847 
   848 
   848 local_setup %gray {*
   849 local_setup %gray {*
   849   LocalTheory.note Thm.theoremK
   850   LocalTheory.note Thm.theoremK
   850     ((@{binding "my_thm_simp"}, 
   851     ((@{binding "my_thm_simp"}, 
   851        [Attrib.internal (K Simplifier.simp_add)]), [my_thm]) #> snd *}
   852        [Attrib.internal (K Simplifier.simp_add)]), [my_thm]) #> snd *}
   852 
   853 
   853 text {*
   854 text {*
   854   Note that we have to use another name under which the theorem is stored,
   855   Note that we have to use another name under which the theorem is stored,
   855   since Isabelle does not allow us to store two theorems under the same
   856   since Isabelle does not allow us to call  @{ML_ind note in LocalTheory} twice
   856   name. The attribute needs to be wrapped inside the function @{ML_ind
   857   with the same name. The attribute needs to be wrapped inside the function @{ML_ind
   857   internal in Attrib}. If we use the function @{ML get_thm_names_from_ss} from
   858   internal in Attrib} from the structure @{ML_struct Attrib}. If we use the function 
       
   859   @{ML get_thm_names_from_ss} from
   858   the previous chapter, we can check whether the theorem has actually been
   860   the previous chapter, we can check whether the theorem has actually been
   859   added.
   861   added.
   860 
   862 
   861 
   863 
   862   @{ML_response [display,gray]
   864   @{ML_response [display,gray]
   952   For the functions @{text "assume"}, @{text "forall_elim"} etc 
   954   For the functions @{text "assume"}, @{text "forall_elim"} etc 
   953   see \isccite{sec:thms}. The basic functions for theorems are defined in
   955   see \isccite{sec:thms}. The basic functions for theorems are defined in
   954   @{ML_file "Pure/thm.ML"}, @{ML_file "Pure/more_thm.ML"} and @{ML_file "Pure/drule.ML"}. 
   956   @{ML_file "Pure/thm.ML"}, @{ML_file "Pure/more_thm.ML"} and @{ML_file "Pure/drule.ML"}. 
   955   \end{readmore}
   957   \end{readmore}
   956 
   958 
   957   The simplifier can be used to unfold definition in theorms. To show
   959   The simplifier can be used to unfold definition in theorems. To show
   958   this we build the theorem @{term "True \<equiv> True"} (Line 1) and then 
   960   this we build the theorem @{term "True \<equiv> True"} (Line 1) and then 
   959   unfold the constant @{term "True"} according to its definition (Line 2).
   961   unfold the constant @{term "True"} according to its definition (Line 2).
   960 
   962 
   961   @{ML_response_fake [display,gray,linenos]
   963   @{ML_response_fake [display,gray,linenos]
   962   "Thm.reflexive @{cterm \"True\"}
   964   "Thm.reflexive @{cterm \"True\"}
   964   |> string_of_thm @{context}
   966   |> string_of_thm @{context}
   965   |> tracing"
   967   |> tracing"
   966   "(\<lambda>x. x) = (\<lambda>x. x) \<equiv> (\<lambda>x. x) = (\<lambda>x. x)"}
   968   "(\<lambda>x. x) = (\<lambda>x. x) \<equiv> (\<lambda>x. x) = (\<lambda>x. x)"}
   967 
   969 
   968   Often it is necessary to transform theorems to and from the object 
   970   Often it is necessary to transform theorems to and from the object 
   969   logic, that is eplacing all @{text "\<longrightarrow>"} and @{text "\<forall>"} with @{text "\<Longrightarrow>"} 
   971   logic, that is replacing all @{text "\<longrightarrow>"} and @{text "\<forall>"} by @{text "\<Longrightarrow>"} 
   970   and @{text "\<And>"}, respectively.  A reason for such transformations is 
   972   and @{text "\<And>"}, or the other way around.  A reason for such a transformation 
   971   that definitions can only be stated using object logic connectives, while 
   973   might be stating a definition. The reason is that definitions can only be 
   972   theorems using the connectives from the meta logic are more convenient for 
   974   stated using object logic connectives, while theorems using the connectives 
   973   reasoning. The function  @{ML_ind rulify in ObjectLogic} replaces all 
   975   from the meta logic are more convenient for reasoning. Therefore there are
   974   object connectives by equivalents in the meta logic. For example
   976   some build in functions which help with these transformations. The function 
       
   977   @{ML_ind rulify in ObjectLogic} 
       
   978   replaces all object connectives by equivalents in the meta logic. For example
   975 
   979 
   976   @{ML_response_fake [display, gray]
   980   @{ML_response_fake [display, gray]
   977   "ObjectLogic.rulify @{thm foo_test2}"
   981   "ObjectLogic.rulify @{thm foo_test2}"
   978   "\<lbrakk>?A; ?B\<rbrakk> \<Longrightarrow> ?C"}
   982   "\<lbrakk>?A; ?B\<rbrakk> \<Longrightarrow> ?C"}
   979 
   983 
   991 
   995 
   992   In this code the function @{ML atomize in ObjectLogic} produces 
   996   In this code the function @{ML atomize in ObjectLogic} produces 
   993   a meta-equation between the given theorem and the theorem transformed
   997   a meta-equation between the given theorem and the theorem transformed
   994   into the object logic. The result is the theorem with object logic 
   998   into the object logic. The result is the theorem with object logic 
   995   connectives. However, in order to completely transform a theorem
   999   connectives. However, in order to completely transform a theorem
   996   such as @{thm [source] list.induct}, which is of the form 
  1000   involving meta variables, such as @{thm [source] list.induct}, which 
       
  1001   is of the form 
   997 
  1002 
   998   @{thm [display] list.induct}
  1003   @{thm [display] list.induct}
   999 
  1004 
  1000   we have to first abstract over the meta variables @{text "?P"} and 
  1005   we have to first abstract over the meta variables @{text "?P"} and 
  1001   @{text "?list"} in the theorem. For this we can use the function 
  1006   @{text "?list"}. For this we can use the function 
  1002   @{ML_ind forall_intr_vars in Drule}. This allows us to implement the
  1007   @{ML_ind forall_intr_vars in Drule}. This allows us to implement the
  1003   following function for atomizing a theorem.
  1008   following function for atomizing a theorem.
  1004 *}
  1009 *}
  1005 
  1010 
  1006 ML{*fun atomize_thm thm =
  1011 ML{*fun atomize_thm thm =
  1017   @{ML_response_fake [display, gray]
  1022   @{ML_response_fake [display, gray]
  1018   "atomize_thm @{thm list.induct}"
  1023   "atomize_thm @{thm list.induct}"
  1019   "\<forall>P list. P [] \<longrightarrow> (\<forall>a list. P list \<longrightarrow> P (a # list)) \<longrightarrow> P list"}
  1024   "\<forall>P list. P [] \<longrightarrow> (\<forall>a list. P list \<longrightarrow> P (a # list)) \<longrightarrow> P list"}
  1020 
  1025 
  1021   Theorems can also be produced from terms by giving an explicit proof. 
  1026   Theorems can also be produced from terms by giving an explicit proof. 
  1022   One way to achive this is by using the function @{ML_ind prove in Goal}
  1027   One way to achieve this is by using the function @{ML_ind prove in Goal}
  1023   in the structure @{ML_struct Goal}. For example below we prove the term 
  1028   in the structure @{ML_struct Goal}. For example below we use this function
  1024   @{term "P \<Longrightarrow> P"}.
  1029   to prove the term @{term "P \<Longrightarrow> P"}.
  1025   
  1030   
  1026   @{ML_response_fake [display,gray]
  1031   @{ML_response_fake [display,gray]
  1027   "let
  1032   "let
  1028   val trm = @{term \"P \<Longrightarrow> P::bool\"}
  1033   val trm = @{term \"P \<Longrightarrow> P::bool\"}
  1029   val tac = K (atac 1)
  1034   val tac = K (atac 1)
  1033   "?P \<Longrightarrow> ?P"}
  1038   "?P \<Longrightarrow> ?P"}
  1034 
  1039 
  1035   This function takes first a context and second a list of strings. This list
  1040   This function takes first a context and second a list of strings. This list
  1036   specifies which variables should be turned into meta-variables once the term
  1041   specifies which variables should be turned into meta-variables once the term
  1037   is proved.  The fourth argument is the term to be proved. The fifth is a
  1042   is proved.  The fourth argument is the term to be proved. The fifth is a
  1038   corresponding proof given in form of a tactic. We explain tactics in
  1043   corresponding proof given in form of a tactic (we explain tactics in
  1039   Chapter~\ref{chp:tactical}. In the code above, the tactic proves the theorem
  1044   Chapter~\ref{chp:tactical}). In the code above, the tactic proves the theorem
  1040   by assumption.
  1045   by assumption. As before this code will produce a theorem, but the theorem
       
  1046   is not yet stored in the theorem database. 
  1041 
  1047 
  1042   Theorems also contain auxiliary data, such as the name of the theorem, its
  1048   Theorems also contain auxiliary data, such as the name of the theorem, its
  1043   kind, the names for cases and so on. This data is stored in a string-string
  1049   kind, the names for cases and so on. This data is stored in a string-string
  1044   list and can be retrieved with the function @{ML_ind get_tags in
  1050   list and can be retrieved with the function @{ML_ind get_tags in
  1045   Thm}. Assume the following lemma.
  1051   Thm}. Assume you prove the following lemma.
  1046 *}
  1052 *}
  1047 
  1053 
  1048 lemma foo_data: "P \<Longrightarrow> P \<Longrightarrow> P" by assumption
  1054 lemma foo_data: 
  1049 
  1055   shows "P \<Longrightarrow> P \<Longrightarrow> P" by assumption
  1050 text {*
  1056 
  1051   So far the the auxiliary data of this lemma is: 
  1057 text {*
       
  1058   The auxiliary data of this lemma can be retrieved using the function 
       
  1059   @{ML_ind get_tags in Thm}. So far the the auxiliary data of this lemma is 
  1052 
  1060 
  1053   @{ML_response_fake [display,gray]
  1061   @{ML_response_fake [display,gray]
  1054   "Thm.get_tags @{thm foo_data}"
  1062   "Thm.get_tags @{thm foo_data}"
  1055   "[(\"name\", \"General.foo_data\"), (\"kind\", \"lemma\")]"}
  1063   "[(\"name\", \"General.foo_data\"), (\"kind\", \"lemma\")]"}
  1056 
  1064 
  1057   When we store lemmas in the theorem database, we may want to explicitly extend 
  1065   consisting of a name and a kind.  When we store lemmas in the theorem database, 
  1058   this data by attaching case names to the two premises of the lemma.  This can
  1066   we might want to explicitly extend this data by attaching case names to the 
  1059   be achieved with the function @{ML_ind name in RuleCases}.
  1067   two premises of the lemma.  This can be done with the function @{ML_ind name in RuleCases}
       
  1068   from the structure @{ML_struct RuleCases}.
  1060 *}
  1069 *}
  1061 
  1070 
  1062 local_setup %gray {*
  1071 local_setup %gray {*
  1063   LocalTheory.note Thm.lemmaK
  1072   LocalTheory.note Thm.lemmaK
  1064     ((@{binding "foo_data'"}, []), 
  1073     ((@{binding "foo_data'"}, []), 
  1071   @{ML_response_fake [display,gray]
  1080   @{ML_response_fake [display,gray]
  1072   "Thm.get_tags @{thm foo_data'}"
  1081   "Thm.get_tags @{thm foo_data'}"
  1073   "[(\"name\", \"General.foo_data'\"), (\"kind\", \"lemma\"), 
  1082   "[(\"name\", \"General.foo_data'\"), (\"kind\", \"lemma\"), 
  1074  (\"case_names\", \"foo_case_one;foo_case_two\")]"}
  1083  (\"case_names\", \"foo_case_one;foo_case_two\")]"}
  1075 
  1084 
  1076   You can notice the case names on the user level when using the proof 
  1085   You can observe the case names of this lemma on the user level when using 
  1077   methods @{ML_text cases} and @{ML_text induct}. In the proof below
  1086   the proof methods @{ML_text cases} and @{ML_text induct}. In the proof below
  1078 *}
  1087 *}
  1079 
  1088 
  1080 lemma
  1089 lemma
  1081   shows "Q \<Longrightarrow> Q \<Longrightarrow> Q"
  1090   shows "Q \<Longrightarrow> Q \<Longrightarrow> Q"
  1082 proof (cases rule: foo_data')
  1091 proof (cases rule: foo_data')
  1091 @{text ">   foo_case_two:"}\\
  1100 @{text ">   foo_case_two:"}\\
  1092 @{text ">     let \"?case\" = \"?P\""}
  1101 @{text ">     let \"?case\" = \"?P\""}
  1093 \end{tabular}*}
  1102 \end{tabular}*}
  1094 
  1103 
  1095 text {*
  1104 text {*
  1096   we can proceed by analysing the cases @{text "foo_case1"} and 
  1105   we can proceed by analysing the cases @{text "foo_case_one"} and 
  1097   @{text "foo_case2"}. While if the theorem has no names, then
  1106   @{text "foo_case_two"}. While if the theorem has no names, then
  1098   the cases have standard names @{text 1}, @{text 2} and so 
  1107   the cases have standard names @{text 1}, @{text 2} and so 
  1099   on. This can be seen in the proof below.
  1108   on. This can be seen in the proof below.
  1100 *}
  1109 *}
  1101 
  1110 
  1102 lemma
  1111 lemma
  1115 \end{tabular}*}
  1124 \end{tabular}*}
  1116 
  1125 
  1117 
  1126 
  1118 text {*
  1127 text {*
  1119   One great feature of Isabelle is its document preparation system, where
  1128   One great feature of Isabelle is its document preparation system, where
  1120   proved theorems can be quoted in the text directly from the formalisation. 
  1129   proved theorems can be quoted in documents referencing directly their
  1121   This helps minimises cut-and-paste errors. However, sometimes the verbatim
  1130   formalisation. This helps tremendously to minimise cut-and-paste errors. However,
  1122   quoting is not what is wanted. For such situations Isabelle allows the
  1131   sometimes the verbatim quoting is not what is wanted or what can be shown to
  1123   installation of \emph{styles}. These are, roughly speaking, functions from 
  1132   readers. For such situations Isabelle allows the installation of \emph{theorem 
  1124   terms to terms. The input term stands for the theorem to be presented.
  1133   styles}. These are, roughly speaking, functions from terms to terms. The input 
  1125   Let us assume we want to display theorems without leading quantifiers. 
  1134   term stands for the theorem to be presented; the output can be constructed to
  1126   For this we can implement the following function that strips off 
  1135   ones wishes.  Let us, for example, assume we want to quote theorems without
  1127   meta-quantifiers.
  1136   leading @{text \<forall>}-quantifiers. For this we can implement the following function 
  1128 *}
  1137   that strips off meta-quantifiers.
  1129 
  1138 *}
  1130 ML {*fun strip_all (Const (@{const_name "All"}, _) $ Abs body) = 
  1139 
  1131       Term.dest_abs body |> snd |> strip_all
  1140 ML %linenosgray {*fun strip_all_qnt (Const (@{const_name "All"}, _) $ Abs body) = 
  1132   | strip_all (Const (@{const_name "Trueprop"}, _) $ t) = strip_all t
  1141       Term.dest_abs body |> snd |> strip_all_qnt
  1133   | strip_all t = t*}
  1142   | strip_all_qnt (Const (@{const_name "Trueprop"}, _) $ t) = 
  1134 
  1143       strip_all_qnt t
  1135 ML {* strip_all @{term "\<forall>x y z. P x y z"}*}
  1144   | strip_all_qnt t = t*}
  1136 
  1145 
  1137 text {*
  1146 text {*
  1138   Now we can install this function as the theorem style named 
  1147   We use in Line 2 the function @{ML_ind dest_abs in Term} for deconstructing abstractions,
  1139   @{text "strip_all"}. 
  1148   since this function deals correctly with potential name clashes. This function produces
       
  1149   a pair consisting of the variable and the body of the abstraction. We are only interested
       
  1150   in the body, which we feed into the recursive call. In Line 3 and 4, we also
       
  1151   have to explicitly strip of the outermost @{term Trueprop}-coercion. Now we can 
       
  1152   install this function as the theorem style named @{text "my_strip_all_qnt"}. 
  1140 *}
  1153 *}
  1141 
  1154 
  1142 setup %gray {*
  1155 setup %gray {*
  1143   Term_Style.setup "strip_all" (Scan.succeed (K strip_all)) 
  1156   Term_Style.setup "my_strip_all_qnt" (Scan.succeed (K strip_all_qnt)) 
  1144 *}
  1157 *}
  1145 
  1158 
  1146 text {*
  1159 text {*
  1147   We can test the theorem style with the following theorem
  1160   We can test this theorem style with the following theorem
  1148 *}
  1161 *}
  1149 
  1162 
  1150 theorem style_test:
  1163 theorem style_test:
  1151   shows "\<forall>x y z. (x, x) = (y, z)" sorry
  1164   shows "\<forall>x y z. (x, x) = (y, z)" sorry
  1152 
  1165 
  1153 text {*
  1166 text {*
  1154   Now printing out the theorem @{thm [source] style_test} normally
  1167   Now printing out in a document the theorem @{thm [source] style_test} normally
  1155   in a document produces
  1168   using @{text "@{thm \<dots>}"} produces
  1156 
  1169 
  1157   @{thm [display] style_test}
  1170   \begin{isabelle}
  1158 
  1171   @{text "@{thm style_test}"}\\
  1159   as expected. But with the theorem style @{text "@{thm (strip_all) \<dots>}"} 
  1172   @{text ">"}~@{thm style_test}
       
  1173   \end{isabelle}
       
  1174 
       
  1175   as expected. But with the theorem style @{text "@{thm (my_strip_all_qnt) \<dots>}"} 
  1160   we obtain
  1176   we obtain
  1161 
  1177 
  1162   @{thm [display] (strip_all) style_test}
  1178   \begin{isabelle}
  1163   
  1179   @{text "@{thm (my_strip_all_qnt) style_test}"}\\
  1164   without the leading quantifiers. Such theorem styles allow one to
  1180   @{text ">"}~@{thm (my_strip_all_qnt) style_test}\\
  1165   print out theorems in documents formatted in any way wanted. Next we 
  1181   \end{isabelle}
  1166   explain theorem attributes, which is another mechanism for treating
  1182   
  1167   theorems.
  1183   without the leading quantifiers. We can improve this theorem style by explicitly 
  1168 *}
  1184   giving a list of strings that should be used for the replacement of the
  1169 
  1185   variables. For this we implement the function which takes a list of strings
       
  1186   and uses them as name in the outermost abstractions.
       
  1187 *}
       
  1188 
       
  1189 ML {*fun rename_all [] t = t
       
  1190   | rename_all (x::xs) (Const (@{const_name "All"}, U) $ Abs (_, T, t)) = 
       
  1191       Const (@{const_name "All"}, U) $ Abs (x, T, rename_all xs t)
       
  1192   | rename_all xs (Const (@{const_name "Trueprop"}, U) $ t) =
       
  1193       rename_all xs t
       
  1194   | rename_all _ t = t*}
       
  1195 
       
  1196 text {*
       
  1197   We can now install a the modified theorem style as follows
       
  1198 *}
       
  1199 
       
  1200 setup %gray {*
       
  1201 let
       
  1202   val parser = Scan.repeat Args.name
       
  1203   fun action xs = K (rename_all xs #> strip_all_qnt)
       
  1204 in
       
  1205   Term_Style.setup "my_strip_all_qnt2" (parser >> action)
       
  1206 end *}
       
  1207 
       
  1208 text {*
       
  1209   We can now suggest, for example, two variables for stripping 
       
  1210   off the @{text \<forall>}-quantifiers, namely:
       
  1211 
       
  1212   \begin{isabelle}
       
  1213   @{text "@{thm (my_strip_all_qnt2 x' x'') style_test}"}\\
       
  1214   @{text ">"}~@{thm (my_strip_all_qnt2 x' x'') style_test}
       
  1215   \end{isabelle}
       
  1216 
       
  1217   Such theorem styles allow one to print out theorems in documents formatted to
       
  1218   ones heart content. Next we explain theorem attributes, which is another
       
  1219   mechanism for dealing with theorems.
       
  1220 
       
  1221   \begin{readmore}
       
  1222   Theorem styles are implemented in @{ML_file "Pure/Thy/term_style.ML"}.
       
  1223   \end{readmore}
       
  1224 *}
  1170 
  1225 
  1171 section {* Theorem Attributes\label{sec:attributes} *}
  1226 section {* Theorem Attributes\label{sec:attributes} *}
  1172 
  1227 
  1173 text {*
  1228 text {*
  1174   Theorem attributes are @{text "[symmetric]"}, @{text "[THEN \<dots>]"}, @{text
  1229   Theorem attributes are @{text "[symmetric]"}, @{text "[THEN \<dots>]"}, @{text