CookBook/Tactical.thy
changeset 131 8db9195bb3e9
parent 130 a21d7b300616
child 132 2d9198bcb850
equal deleted inserted replaced
130:a21d7b300616 131:8db9195bb3e9
   796   then you can use the combinator @{ML ORELSE'} for two tactics, and @{ML
   796   then you can use the combinator @{ML ORELSE'} for two tactics, and @{ML
   797   FIRST'} (or @{ML FIRST1}) for a list of tactics. For example, the tactic
   797   FIRST'} (or @{ML FIRST1}) for a list of tactics. For example, the tactic
   798 
   798 
   799 *}
   799 *}
   800 
   800 
   801 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*}
   801 ML{*val orelse_xmp = rtac @{thm disjI1} ORELSE' rtac @{thm conjI}*}
   802 
   802 
   803 text {*
   803 text {*
   804   will first try out whether rule @{text disjI} applies and after that 
   804   will first try out whether rule @{text disjI} applies and after that 
   805   @{text conjI}. To see this consider the proof
   805   @{text conjI}. To see this consider the proof
   806 *}
   806 *}
  1057 simproc_setup fail_sp ("Suc n") = {* K fail_sp_aux *}
  1057 simproc_setup fail_sp ("Suc n") = {* K fail_sp_aux *}
  1058 
  1058 
  1059 text {*
  1059 text {*
  1060   where the second argument specifies the pattern and the right-hand side
  1060   where the second argument specifies the pattern and the right-hand side
  1061   contains the code of the simproc (we have to use @{ML K} since we ignoring
  1061   contains the code of the simproc (we have to use @{ML K} since we ignoring
  1062   an argument about a morphism\footnote{FIXME: what does the morphism do?}). 
  1062   an argument about morphisms\footnote{FIXME: what does the morphism do?}). 
  1063   After this, the simplifier is aware of the simproc and you can test whether 
  1063   After this, the simplifier is aware of the simproc and you can test whether 
  1064   it fires on the lemma
  1064   it fires on the lemma:
  1065 *}
  1065 *}
  1066 
  1066 
  1067 lemma shows "Suc 0 = 1"
  1067 lemma shows "Suc 0 = 1"
  1068 apply(simp)
  1068   apply(simp)
  1069 (*<*)oops(*>*)
  1069 (*<*)oops(*>*)
  1070 
  1070 
  1071 text {*
  1071 text {*
  1072   This will print out the message twice: once for the left-hand side and
  1072   This will print out the message twice: once for the left-hand side and
  1073   once for the right-hand side. The reason is that during simplification the
  1073   once for the right-hand side. The reason is that during simplification the
  1074   simplifier will at some point reduce the term @{term "1::nat"} to @{term "Suc
  1074   simplifier will at some point reduce the term @{term "1::nat"} to @{term "Suc
  1075   0"}, and then the simproc ``fires'' also on that term. 
  1075   0"}, and then the simproc ``fires'' also on that term. 
  1076 
  1076 
  1077   We can add or delete the simproc by the usual \isacommand{declare}-statement. 
  1077   We can add or delete the simproc from the current simpset by the usual 
  1078   For example the simproc will be deleted if you type:
  1078   \isacommand{declare}-statement. For example the simproc will be deleted 
       
  1079   if you type:
  1079 *}
  1080 *}
  1080 
  1081 
  1081 declare [[simproc del: fail_sp]]
  1082 declare [[simproc del: fail_sp]]
  1082 
  1083 
  1083 text {*
  1084 text {*
  1085   interference from other rewrite rules, you can call @{text fail_sp} 
  1086   interference from other rewrite rules, you can call @{text fail_sp} 
  1086   as follows:
  1087   as follows:
  1087 *}
  1088 *}
  1088 
  1089 
  1089 lemma shows "Suc 0 = 1"
  1090 lemma shows "Suc 0 = 1"
  1090 apply(tactic {* simp_tac (HOL_ss addsimprocs [@{simproc fail_sp}]) 1*})
  1091   apply(tactic {* simp_tac (HOL_ss addsimprocs [@{simproc fail_sp}]) 1*})
  1091 (*<*)oops(*>*)
  1092 (*<*)oops(*>*)
  1092 
  1093 
  1093 text {*
  1094 text {*
  1094   (FIXME: should one use HOL-basic-ss or HOL-ss?)
  1095   (FIXME: should one use HOL-basic-ss or HOL-ss?)
  1095 
  1096 
  1096   Now the message shows up only once since @{term "1::nat"} is left unchanged. 
  1097   Now the message shows up only once since the term @{term "1::nat"} is 
       
  1098   left unchanged. 
  1097 
  1099 
  1098   Setting up a simproc using the command \isacommand{setup\_simproc} will
  1100   Setting up a simproc using the command \isacommand{setup\_simproc} will
  1099   always add automatically the simproc to the current simpset. If you do not
  1101   always add automatically the simproc to the current simpset. If you do not
  1100   want this, then you have to use a slightly different method for setting 
  1102   want this, then you have to use a slightly different method for setting 
  1101   up the simproc. First the function @{ML fail_sp_aux} needs to be modified
  1103   up the simproc. First the function @{ML fail_sp_aux} needs to be modified
  1131   It might be interesting to notice that simprocs are applied from inside 
  1133   It might be interesting to notice that simprocs are applied from inside 
  1132   to outside and from left to right. You can see this in the proof
  1134   to outside and from left to right. You can see this in the proof
  1133 *}
  1135 *}
  1134 
  1136 
  1135 lemma shows "Suc (Suc 0) = (Suc 1)"
  1137 lemma shows "Suc (Suc 0) = (Suc 1)"
  1136 apply(tactic {* simp_tac (HOL_ss addsimprocs [fail_sp']) 1*})
  1138   apply(tactic {* simp_tac (HOL_ss addsimprocs [fail_sp']) 1*})
  1137 (*<*)oops(*>*)
  1139 (*<*)oops(*>*)
  1138 
  1140 
  1139 text {*
  1141 text {*
  1140   since the @{ML fail_sp'}-simproc prints out the sequence 
  1142   since @{ML fail_sp'} prints out the sequence 
  1141 
  1143 
  1142 @{text [display]
  1144 @{text [display]
  1143 "> Suc 0
  1145 "> Suc 0
  1144 > Suc (Suc 0) 
  1146 > Suc (Suc 0) 
  1145 > Suc 1"}
  1147 > Suc 1"}
  1146 
  1148 
  1147   To see how a simproc applies a theorem  let us implement a simproc that
  1149   To see how a simproc applies a theorem,  let us implement a simproc that
  1148   rewrites terms according to the equation:
  1150   rewrites terms according to the equation:
  1149 *}
  1151 *}
  1150 
  1152 
  1151 lemma plus_one: 
  1153 lemma plus_one: 
  1152   shows "Suc n \<equiv> n + 1" by simp
  1154   shows "Suc n \<equiv> n + 1" by simp
  1153 
  1155 
  1154 text {*
  1156 text {*
  1155   Simprocs expect that the given equation is a meta-equation, however the
  1157   Simprocs expect that the given equation is a meta-equation, however the
  1156   equation can contain preconditions (the simproc then will only fire if the 
  1158   equation can contain preconditions (the simproc then will only fire if the
  1157   preconditions can be solved). To see how rewriting can be tuned precisely, let us 
  1159   preconditions can be solved). To see one has relatively precise control over
  1158   further assume we want that the simproc only rewrites terms greater than 
  1160   the rewriting with simprocs, let us further assume we want that the simproc
  1159   @{term "Suc 0"}. For this we can write
  1161   only rewrites terms ``greater'' than @{term "Suc 0"}. For this we can write 
  1160 *}
  1162 *}
       
  1163 
  1161 
  1164 
  1162 ML{*fun plus_one_sp_aux ss redex =
  1165 ML{*fun plus_one_sp_aux ss redex =
  1163   case redex of
  1166   case redex of
  1164     @{term "Suc 0"} => NONE
  1167     @{term "Suc 0"} => NONE
  1165   | _ => SOME @{thm plus_one}*}
  1168   | _ => SOME @{thm plus_one}*}
  1175   in
  1178   in
  1176     Simplifier.simproc_i thy "sproc +1" pat (K plus_one_sp_aux)
  1179     Simplifier.simproc_i thy "sproc +1" pat (K plus_one_sp_aux)
  1177   end*}
  1180   end*}
  1178 
  1181 
  1179 text {*
  1182 text {*
  1180   Now the have set up the simproc so that it is triggered by terms
  1183   Now the simproc is set up xso that it is triggered by terms
  1181   of the form @{term "Suc n"}, but inside the simproc we only produce
  1184   of the form @{term "Suc n"}, but inside the simproc we only produce
  1182   a theorem if the term is not @{term "Suc 0"}. The result you can see
  1185   a theorem if the term is not @{term "Suc 0"}. The result you can see
  1183   in the following proof.
  1186   in the following proof
  1184 *}
  1187 *}
  1185 
  1188 
  1186 lemma shows "P (Suc (Suc (Suc 0))) (Suc 0)"
  1189 lemma shows "P (Suc (Suc (Suc 0))) (Suc 0)"
  1187 apply(tactic {* simp_tac (HOL_ss addsimprocs [plus_one_sp]) 1*})
  1190   apply(tactic {* simp_tac (HOL_ss addsimprocs [plus_one_sp]) 1*})
  1188 txt{*
  1191 txt{*
  1189   the simproc produces the goal state
  1192   where the simproc produces the goal state
  1190 
  1193 
  1191   @{subgoals[display]}
  1194   @{subgoals[display]}
  1192 *}  
  1195 *}  
  1193 (*<*)oops(*>*)
  1196 (*<*)oops(*>*)
  1194 
  1197 
  1195 text {*
  1198 text {*
  1196   As usual with simplification you have to be careful with loops: you already have
  1199   As usual with simplification you have to be careful with looping: you already have
  1197   one @{ML plus_one_sp}, if you apply if with the default simpset (because
  1200   one @{ML plus_one_sp}, if you apply if with the default simpset (because
  1198   the default simpset contains a rule which just undoes the rewriting 
  1201   the default simpset contains a rule which just undoes the rewriting 
  1199   @{ML plus_one_sp}).
  1202   @{ML plus_one_sp}).
  1200 
  1203 
  1201   Let us next implement a simproc that replaces terms of the form @{term "Suc n"}
  1204   Let us next implement a simproc that replaces terms of the form @{term "Suc n"}
  1208   | dest_suc_trm t = snd (HOLogic.dest_number t)*}
  1211   | dest_suc_trm t = snd (HOLogic.dest_number t)*}
  1209 
  1212 
  1210 text {* 
  1213 text {* 
  1211   It uses the library function @{ML dest_number in HOLogic} that transforms
  1214   It uses the library function @{ML dest_number in HOLogic} that transforms
  1212   (Isabelle) terms, like @{term "0::nat"}, @{term "1::nat"}, @{term "2::nat"} and so
  1215   (Isabelle) terms, like @{term "0::nat"}, @{term "1::nat"}, @{term "2::nat"} and so
  1213   on, into integer values. This function raises the exception @{ML TERM} if
  1216   on, into integer values. This function raises the exception @{ML TERM}, if
  1214   the term is not a number. The next function expects a pair consisting of a term
  1217   the term is not a number. The next function expects a pair consisting of a term
  1215   @{text t} and the corresponding integer value @{text n}. 
  1218   @{text t} (containing @{term Suc}s) and the corresponding integer value @{text n}. 
  1216 *}
  1219 *}
  1217 
  1220 
  1218 ML %linenosgray{*fun get_thm ctxt (t, n) =
  1221 ML %linenosgray{*fun get_thm ctxt (t, n) =
  1219 let
  1222 let
  1220   val num = HOLogic.mk_number @{typ "nat"} n
  1223   val num = HOLogic.mk_number @{typ "nat"} n
  1222 in
  1225 in
  1223   mk_meta_eq (Goal.prove ctxt [] [] goal (K (simp_tac @{simpset} 1)))
  1226   mk_meta_eq (Goal.prove ctxt [] [] goal (K (simp_tac @{simpset} 1)))
  1224 end*}
  1227 end*}
  1225 
  1228 
  1226 text {*
  1229 text {*
  1227   From the integer value it generates the corresponding Isabelle term, called 
  1230   (FIXME: is @{text "@{simpset}"} kosher here? Otherwise the following will loop.)
  1228   @{text num} (Line 3), and then generates the equation @{text "t = num"} (Line 4)
  1231 
       
  1232   From the integer value it generates the corresponding number term, called 
       
  1233   @{text num} (Line 3), and then generates the equation @{text "t = num"} (Line 4),
  1229   which it proves by simplification in Line 6. The function @{ML mk_meta_eq} 
  1234   which it proves by simplification in Line 6. The function @{ML mk_meta_eq} 
  1230   at the outside of the proof just transforms the equality to a meta-equality.
  1235   at the outside of the proof just transforms the equality into a meta-equality.
  1231 
  1236 
  1232   Both functions can be stringed together in the function that produces the 
  1237   Both functions can be stringed together in the function that produces the 
  1233   actual theorem for the simproc.
  1238   actual theorem for the simproc.
  1234 *}
  1239 *}
  1235 
  1240 
  1240   SOME (get_thm ctxt (t, dest_suc_trm t))
  1245   SOME (get_thm ctxt (t, dest_suc_trm t))
  1241   handle TERM _ => NONE
  1246   handle TERM _ => NONE
  1242 end*}
  1247 end*}
  1243 
  1248 
  1244 text {*
  1249 text {*
  1245   (FIXME: is @{text "@{simpset}"} kosher here? Otherwise the following will loop.)
       
  1246 
       
  1247   This function uses the fact that @{ML dest_suc_trm} might throw an exception 
  1250   This function uses the fact that @{ML dest_suc_trm} might throw an exception 
  1248   @{ML TERM}. In this case there is nothing that can be rewritten and therefore no
  1251   @{ML TERM}. In this case there is nothing that can be rewritten and therefore no
  1249   theorem is produced. To try out the simproc on an example, you can set it up as 
  1252   theorem is produced (i.e.~the function returns @{ML NONE}). To try out the simproc 
  1250   follows:
  1253   on an example, you can set it up as follows:
  1251 *}
  1254 *}
  1252 
  1255 
  1253 ML{*val nat_number_sp =
  1256 ML{*val nat_number_sp =
  1254   let
  1257   let
  1255     val thy = @{theory}
  1258     val thy = @{theory}