60 @{text erule}, @{text rule} and @{text assumption}, respectively. |
60 @{text erule}, @{text rule} and @{text assumption}, respectively. |
61 The operator @{ML THEN} strings the tactics together. |
61 The operator @{ML THEN} strings the tactics together. |
62 |
62 |
63 \begin{readmore} |
63 \begin{readmore} |
64 To learn more about the function @{ML Goal.prove} see \isccite{sec:results} |
64 To learn more about the function @{ML Goal.prove} see \isccite{sec:results} |
65 and the file @{ML_file "Pure/goal.ML"}. For more information about the |
65 and the file @{ML_file "Pure/goal.ML"}. See @{ML_file |
66 internals of goals see \isccite{sec:tactical-goals}. See @{ML_file |
|
67 "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic |
66 "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic |
68 tactics and tactic combinators; see also Chapters 3 and 4 in the old |
67 tactics and tactic combinators; see also Chapters 3 and 4 in the old |
69 Isabelle Reference Manual. |
68 Isabelle Reference Manual. |
70 \end{readmore} |
69 \end{readmore} |
71 |
70 |
72 Note that we used antiquotations for referencing the theorems. Many theorems |
71 Note that in the code above we used antiquotations for referencing the theorems. Many theorems |
73 also have ML-bindings with the same name. Therefore, we could also just have |
72 also have ML-bindings with the same name. Therefore, we could also just have |
74 written @{ML "etac disjE 1"}, or in case there are no ML-binding obtained |
73 written @{ML "etac disjE 1"}, or in case there are no ML-binding obtained |
75 the theorem dynamically using the function @{ML thm}; for example |
74 the theorem dynamically using the function @{ML thm}; for example |
76 @{ML "etac (thm \"disjE\") 1"}. Both ways however are considered bad style. |
75 @{ML "etac (thm \"disjE\") 1"}. Both ways however are considered bad style! |
77 The reason |
76 The reason |
78 is that the binding for @{ML disjE} can be re-assigned by the user and thus |
77 is that the binding for @{ML disjE} can be re-assigned by the user and thus |
79 one does not have complete control over which theorem is actually |
78 one does not have complete control over which theorem is actually |
80 applied. This problem is nicely prevented by using antiquotations, because |
79 applied. This problem is nicely prevented by using antiquotations, because |
81 then the theorems are fixed statically at compile-time. |
80 then the theorems are fixed statically at compile-time. |
213 end*} |
212 end*} |
214 |
213 |
215 text {* |
214 text {* |
216 which prints out the given theorem (using the string-function defined |
215 which prints out the given theorem (using the string-function defined |
217 in Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. We |
216 in Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. We |
218 are now in the position to inspect every proof state in a proof. Consider |
217 are now in the position to inspect every goal state in a proof. Consider |
219 the proof below: on the left-hand side we show the goal state as shown |
218 the proof below: on the left-hand side we show the goal state as shown |
220 by Isabelle, on the right-hand side the print out from @{ML my_print_tac}. |
219 by Isabelle, on the right-hand side the print out from @{ML my_print_tac}. |
221 *} |
220 *} |
222 |
221 |
223 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B" |
222 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B" |
224 apply(tactic {* my_print_tac @{context} *}) |
223 apply(tactic {* my_print_tac @{context} *}) |
225 |
224 |
226 txt{* \small |
225 txt{* \small |
227 \begin{tabular}{@ {}l@ {}p{0.7\textwidth}@ {}} |
226 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
228 \begin{minipage}[t]{0.3\textwidth} |
227 \begin{minipage}[t]{0.3\textwidth} |
229 @{subgoals [display]} |
228 @{subgoals [display]} |
230 \end{minipage} & |
229 \end{minipage} & |
231 \hfill@{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
230 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
232 \end{tabular} |
231 \end{tabularstar} |
233 *} |
232 *} |
234 |
233 |
235 apply(rule conjI) |
234 apply(rule conjI) |
236 apply(tactic {* my_print_tac @{context} *}) |
235 apply(tactic {* my_print_tac @{context} *}) |
237 |
236 |
238 txt{* \small |
237 txt{* \small |
239 \begin{tabular}{@ {}l@ {}p{0.76\textwidth}@ {}} |
238 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
240 \begin{minipage}[t]{0.26\textwidth} |
239 \begin{minipage}[t]{0.26\textwidth} |
241 @{subgoals [display]} |
240 @{subgoals [display]} |
242 \end{minipage} & |
241 \end{minipage} & |
243 \hfill@{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
242 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
244 \end{tabular} |
243 \end{tabularstar} |
245 *} |
244 *} |
246 |
245 |
247 apply(assumption) |
246 apply(assumption) |
248 apply(tactic {* my_print_tac @{context} *}) |
247 apply(tactic {* my_print_tac @{context} *}) |
249 |
248 |
250 txt{* \small |
249 txt{* \small |
251 \begin{tabular}{@ {}l@ {}p{0.7\textwidth}@ {}} |
250 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
252 \begin{minipage}[t]{0.3\textwidth} |
251 \begin{minipage}[t]{0.3\textwidth} |
253 @{subgoals [display]} |
252 @{subgoals [display]} |
254 \end{minipage} & |
253 \end{minipage} & |
255 \hfill@{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
254 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
256 \end{tabular} |
255 \end{tabularstar} |
257 *} |
256 *} |
258 |
257 |
259 apply(assumption) |
258 apply(assumption) |
260 apply(tactic {* my_print_tac @{context} *}) |
259 apply(tactic {* my_print_tac @{context} *}) |
261 |
260 |
262 txt{* \small |
261 txt{* \small |
263 \begin{tabular}{@ {}l@ {}p{0.7\textwidth}@ {}} |
262 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
264 \begin{minipage}[t]{0.3\textwidth} |
263 \begin{minipage}[t]{0.3\textwidth} |
265 @{subgoals [display]} |
264 @{subgoals [display]} |
266 \end{minipage} & |
265 \end{minipage} & |
267 \hfill@{text "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"} |
266 @{text "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"} |
268 \end{tabular} |
267 \end{tabularstar} |
269 *} |
268 *} |
270 |
269 |
271 done |
270 done |
272 |
271 |
273 text {* |
272 text {* |
275 |
274 |
276 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
275 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
277 |
276 |
278 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the |
277 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the |
279 subgoals. So after setting up the lemma, the goal state is always of the form |
278 subgoals. So after setting up the lemma, the goal state is always of the form |
280 @{text "C \<Longrightarrow> (C)"}, and when the proof is finished we are left with @{text "(C)"}. |
279 @{text "C \<Longrightarrow> (C)"}; when the proof is finished we are left with @{text "(C)"}. |
281 Since the goal @{term C} can potentially be an implication, |
280 Since the goal @{term C} can potentially be an implication, |
282 there is a ``protector'' wrapped around it (in from of an outermost constant |
281 there is a ``protector'' wrapped around it (in from of an outermost constant |
283 @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal; |
282 @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal; |
284 however this constant is invisible in the print out above). This |
283 however this constant is invisible in the print out above). This |
285 prevents that premises of @{text C} are mis-interpreted as open subgoals. |
284 prevents that premises of @{text C} are mis-interpreted as open subgoals. |
286 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
285 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
287 are expected to leave the conclusion @{term C} intact, with the |
286 are expected to leave the conclusion @{term C} intact, with the |
288 exception of possibly instantiating schematic variables. |
287 exception of possibly instantiating schematic variables. If you use |
|
288 the predefined tactics, this will always be the case. |
289 |
289 |
|
290 \begin{readmore} |
|
291 For more information about the internals of goals see \isccite{sec:tactical-goals}. |
|
292 \end{readmore} |
|
293 |
290 *} |
294 *} |
291 |
295 |
292 section {* Simple Tactics *} |
296 section {* Simple Tactics *} |
293 |
297 |
294 text {* |
298 text {* |
394 \end{minipage}*} |
398 \end{minipage}*} |
395 (*<*)oops(*>*) |
399 (*<*)oops(*>*) |
396 |
400 |
397 text {* |
401 text {* |
398 Since rules are applied using higher-order unification, an automatic proof |
402 Since rules are applied using higher-order unification, an automatic proof |
399 procedure might become too fragile, if it just applies inference rules shown |
403 procedure might become too fragile, if it just applies inference rules as |
400 in the fashion above. More constraints can be introduced by |
404 shown above. The reason is that a number of rules introduce meta-variables |
401 pre-instantiating theorems with other theorems. You can do this using the |
405 into the goal state. Consider for example the proof |
402 function @{ML RS}. For example |
406 *} |
|
407 |
|
408 lemma shows "\<forall>x\<in>A. P x \<Longrightarrow> Q x" |
|
409 apply(drule bspec) |
|
410 txt{*\begin{minipage}{\textwidth} |
|
411 @{subgoals [display]} |
|
412 \end{minipage}*} |
|
413 (*<*)oops(*>*) |
|
414 |
|
415 text {* |
|
416 where the application of @{text bspec} results into two subgoals involving the |
|
417 meta-variable @{text "?x"}. The point is that if you are not careful, tactics |
|
418 applied to the first subgoal might instantiate this meta-variable in such a |
|
419 way that the second subgoal becomes unprovable. If it is clear what the @{text "?x"} |
|
420 should be, then this situation can be avoided by introducing a more |
|
421 constraint version of the @{text bspec}-rule. Such constraints can be enforced by |
|
422 pre-instantiating theorems with other theorems, for example by using the |
|
423 function @{ML RS} |
403 |
424 |
404 @{ML_response_fake [display,gray] |
425 @{ML_response_fake [display,gray] |
405 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
426 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
406 |
427 |
407 instantiates the first premise of the @{text conjI}-rule with the |
428 which, for instance, instantiates the first premise of the @{text conjI}-rule |
408 rule @{text disjI1}. If this is impossible, as in the case of |
429 with the rule @{text disjI1}. If this is impossible, as in the case of |
409 |
430 |
410 @{ML_response_fake_both [display,gray] |
431 @{ML_response_fake_both [display,gray] |
411 "@{thm conjI} RS @{thm mp}" |
432 "@{thm conjI} RS @{thm mp}" |
412 "*** Exception- THM (\"RSN: no unifiers\", 1, |
433 "*** Exception- THM (\"RSN: no unifiers\", 1, |
413 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
434 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
611 | @{term "Not"} $ _ => rtac @{thm notI} i |
632 | @{term "Not"} $ _ => rtac @{thm notI} i |
612 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
633 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
613 | _ => all_tac*} |
634 | _ => all_tac*} |
614 |
635 |
615 text {* |
636 text {* |
616 In line 3 you need to decend under the outermost @{term "Trueprop"} in order |
637 In line 3 you need to descend under the outermost @{term "Trueprop"} in order |
617 to get to the connective you like to analyse. Otherwise goals like @{prop "A \<and> B"} |
638 to get to the connective you like to analyse. Otherwise goals like @{prop "A \<and> B"} |
618 are not properly analysed. While for the first four pattern we can use the |
639 are not properly analysed. While for the first four pattern we can use the |
619 @{text "@term"}-antiquotation, the pattern in Line 7 cannot be constructed |
640 @{text "@term"}-antiquotation, the pattern in Line 7 cannot be constructed |
620 in this way. The reason is that an antiquotation would fix the type of the |
641 in this way. The reason is that an antiquotation would fix the type of the |
621 quantified variable. So you really have to construct the pattern |
642 quantified variable. So you really have to construct the pattern |
622 using the term-constructors. This is not necessary in other cases, because |
643 using the term-constructors. This is not necessary in other cases, because |
623 their type is always something involving @{typ bool}. The final patter is |
644 their type is always something involving @{typ bool}. The final patter is |
624 for the case where the goal does not fall into any of the categorories before. |
645 for the case where the goal does not fall into any of the categories before. |
625 In this case we chose to just return @{ML all_tac} (i.e., @{ML select_tac} |
646 In this case we chose to just return @{ML all_tac} (i.e., @{ML select_tac} |
626 never fails). |
647 never fails). |
627 |
648 |
628 Let us now see how to apply this tactic. Consider the four goals: |
649 Let us now see how to apply this tactic. Consider the four goals: |
629 *} |
650 *} |
657 then we have to be careful to not apply the tactic to the two subgoals the |
678 then we have to be careful to not apply the tactic to the two subgoals the |
658 first goal produced. To do this can result in quite messy code. In contrast, |
679 first goal produced. To do this can result in quite messy code. In contrast, |
659 the ``reverse application'' is easy to implement. |
680 the ``reverse application'' is easy to implement. |
660 |
681 |
661 However, this example is very contrived: there are much simpler methods to implement |
682 However, this example is very contrived: there are much simpler methods to implement |
662 such a proof procedure analying a goal according to its topmost |
683 such a proof procedure analysing a goal according to its topmost |
663 connective. These simpler methods use tactic combinators which will be explained |
684 connective. These simpler methods use tactic combinators which will be explained |
664 in the next section. |
685 in the next section. |
665 *} |
686 *} |
666 |
687 |
667 section {* Tactic Combinators *} |
688 section {* Tactic Combinators *} |
668 |
689 |
669 text {* |
690 text {* |
670 The purpose of tactic combinators is to build powerful tactics out of |
691 The purpose of tactic combinators is to build powerful tactics out of |
671 smaller components. In the previous section we already used @{ML THEN} which |
692 smaller components. In the previous section we already used @{ML THEN}, which |
672 strings two tactics together in sequence. For example: |
693 strings two tactics together in sequence. For example: |
673 *} |
694 *} |
674 |
695 |
675 lemma shows "(Foo \<and> Bar) \<and> False" |
696 lemma shows "(Foo \<and> Bar) \<and> False" |
676 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
697 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
696 in what follows we will usually prefer it over the ``unprimed'' one. |
717 in what follows we will usually prefer it over the ``unprimed'' one. |
697 |
718 |
698 If there is a list of tactics that should all be tried out in |
719 If there is a list of tactics that should all be tried out in |
699 sequence, you can use the combinator @{ML EVERY'}. For example |
720 sequence, you can use the combinator @{ML EVERY'}. For example |
700 the function @{ML foo_tac'} from page~\ref{tac:footacprime} can also |
721 the function @{ML foo_tac'} from page~\ref{tac:footacprime} can also |
701 be written as |
722 be written as: |
702 *} |
723 *} |
703 |
724 |
704 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
725 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
705 atac, rtac @{thm disjI1}, atac]*} |
726 atac, rtac @{thm disjI1}, atac]*} |
706 |
727 |
707 text {* |
728 text {* |
708 There is even another variant for @{ML foo_tac''}: in automatic proof |
729 There is even another way: in automatic proof procedures (in contrast to |
709 procedures (in contrast to tactics that might be called by the user) |
730 tactics that might be called by the user) there are often long lists of |
710 there are often long lists of tactics that are applied to the first |
731 tactics that are applied to the first subgoal. Instead of writing the code |
711 subgoal. Instead of writing the code above and then calling |
732 above and then calling @{ML "foo_tac'' 1"}, you can also just write |
712 @{ML "foo_tac'' 1"}, you can also just write |
|
713 *} |
733 *} |
714 |
734 |
715 ML{*val foo_tac1 = EVERY1 [etac @{thm disjE}, rtac @{thm disjI2}, |
735 ML{*val foo_tac1 = EVERY1 [etac @{thm disjE}, rtac @{thm disjI2}, |
716 atac, rtac @{thm disjI1}, atac]*} |
736 atac, rtac @{thm disjI1}, atac]*} |
717 |
737 |
718 text {* |
738 text {* |
719 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML EVERY1} it must be |
739 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML EVERY1} it must be |
720 guaranteed that all component tactics sucessfully apply; otherwise the |
740 guaranteed that all component tactics successfully apply; otherwise the |
721 whole tactic will fail. If you rather want to try out a number of tactics, |
741 whole tactic will fail. If you rather want to try out a number of tactics, |
722 then you can use the combinator @{ML ORELSE'} for two tactics and @{ML FIRST'} |
742 then you can use the combinator @{ML ORELSE'} for two tactics, and @{ML FIRST'} |
723 (or @{ML FIRST1}) for a list of tactics. For example, the tactic |
743 (or @{ML FIRST1}) for a list of tactics. For example, the tactic |
724 *} |
744 *} |
725 |
745 |
726 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*} |
746 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*} |
727 |
747 |
749 |
769 |
750 ML{*val select_tac' = FIRST' [rtac @{thm conjI}, rtac @{thm impI}, |
770 ML{*val select_tac' = FIRST' [rtac @{thm conjI}, rtac @{thm impI}, |
751 rtac @{thm notI}, rtac @{thm allI}, K all_tac]*} |
771 rtac @{thm notI}, rtac @{thm allI}, K all_tac]*} |
752 |
772 |
753 text {* |
773 text {* |
754 Since we like to mimic the bahaviour of @{ML select_tac}, we must include |
774 Since we like to mimic the behaviour of @{ML select_tac} as closely as possible, |
755 @{ML all_tac} at the end (@{ML all_tac} must also be ``wrapped up'' using |
775 we must include @{ML all_tac} at the end of the list (@{ML all_tac} must also |
756 the @{ML K}-combinator as it does not take a subgoal number as argument). |
776 be ``wrapped up'' using the @{ML K}-combinator, as it does not take a subgoal |
757 We can test the tactic on the same proof: |
777 number as argument). We can test the tactic on the same proof: |
758 *} |
778 *} |
759 |
779 |
760 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
780 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
761 apply(tactic {* select_tac' 4 *}) |
781 apply(tactic {* select_tac' 4 *}) |
762 apply(tactic {* select_tac' 3 *}) |
782 apply(tactic {* select_tac' 3 *}) |
766 @{subgoals [display]} |
786 @{subgoals [display]} |
767 \end{minipage} *} |
787 \end{minipage} *} |
768 (*<*)oops(*>*) |
788 (*<*)oops(*>*) |
769 |
789 |
770 text {* |
790 text {* |
771 and obtain the same subgoals. Since this repeated application of a tactic |
791 Because such repeated applications of a tactic to the reverse order of |
772 to the reverse order of \emph{all} subgoals is quite common, there is |
792 \emph{all} subgoals is quite common, there is the tactics combinator |
773 the tactics combinator @{ML ALLGOALS} that simplifies this. Using this |
793 @{ML ALLGOALS} that simplifies this. Using this combinator we can simply |
774 combinator we can simply write: *} |
794 write: *} |
775 |
795 |
776 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
796 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
777 apply(tactic {* ALLGOALS select_tac' *}) |
797 apply(tactic {* ALLGOALS select_tac' *}) |
778 txt{* \begin{minipage}{\textwidth} |
798 txt{* \begin{minipage}{\textwidth} |
779 @{subgoals [display]} |
799 @{subgoals [display]} |
780 \end{minipage} *} |
800 \end{minipage} *} |
781 (*<*)oops(*>*) |
801 (*<*)oops(*>*) |
782 |
802 |
783 text {* |
803 text {* |
784 We chose to write @{ML select_tac'} in such a way that it always succeeds. |
804 Remember that we chose to write @{ML select_tac'} in such a way that it always |
785 This can be potetially very confusing for the user in cases of goals |
805 succeeds. This can be potentially very confusing for the user, for example, |
786 of the form |
806 in cases the goals is the form |
787 *} |
807 *} |
788 |
808 |
789 lemma shows "E \<Longrightarrow> F" |
809 lemma shows "E \<Longrightarrow> F" |
790 apply(tactic {* select_tac' 1 *}) |
810 apply(tactic {* select_tac' 1 *}) |
791 txt{* \begin{minipage}{\textwidth} |
811 txt{* \begin{minipage}{\textwidth} |
794 (*<*)oops(*>*) |
814 (*<*)oops(*>*) |
795 |
815 |
796 text {* |
816 text {* |
797 where no rule applies. The reason is that the user has little chance |
817 where no rule applies. The reason is that the user has little chance |
798 to see whether progress in the proof has been made or not. We could simply |
818 to see whether progress in the proof has been made or not. We could simply |
799 remove @{ML "K all_tac"} from the end of the list. Then the tactic would |
819 delete th @{ML "K all_tac"} from the end of the list. Then @{ML select_tac'} |
800 only apply in cases where it can make some progress. But for the sake of |
820 would only succeed on goals where it can make progress. But for the sake of |
801 argument, let us assume that this is not an option. In such cases, you |
821 argument, let us suppose that this deletion is not an option. In such cases, you |
802 can use the combinator @{ML CHANGED} to make sure the subgoal has been |
822 can use the combinator @{ML CHANGED} to make sure the subgoal has been |
803 changed by the tactic. Because now |
823 changed by the tactic. Because now |
804 *} |
824 *} |
805 |
825 |
806 lemma shows "E \<Longrightarrow> F" |
826 lemma shows "E \<Longrightarrow> F" |
807 apply(tactic {* CHANGED (select_tac' 1) *})(*<*)?(*>*) |
827 apply(tactic {* CHANGED (select_tac' 1) *})(*<*)?(*>*) |
808 txt{* results in the usual error message for empty result sequences. *} |
828 txt{* results in the error message: |
809 (*<*)oops(*>*) |
829 \begin{isabelle} |
810 |
830 @{text "*** empty result sequence -- proof command failed"}\\ |
811 |
831 @{text "*** At command \"apply\"."} |
812 text {* |
832 \end{isabelle} |
813 |
833 *}(*<*)oops(*>*) |
814 @{ML REPEAT} @{ML DETERM} |
834 |
815 |
835 |
816 @{ML CHANGED} |
836 text {* |
|
837 Meaning the tactic failed. |
|
838 |
|
839 We can extend @{ML select_tac'} so that it not just applies to the top-most |
|
840 connective, but also to the ones immediately ``underneath''. For this you can use the |
|
841 tactic combinator @{ML REPEAT}. For example suppose the following tactic |
|
842 *} |
|
843 |
|
844 ML{*val repeat_xmp = REPEAT (CHANGED (select_tac' 1)) *} |
|
845 |
|
846 text {* and the proof *} |
|
847 |
|
848 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
|
849 apply(tactic {* repeat_xmp *}) |
|
850 txt{* \begin{minipage}{\textwidth} |
|
851 @{subgoals [display]} |
|
852 \end{minipage} *} |
|
853 (*<*)oops(*>*) |
|
854 |
|
855 text {* |
|
856 Here it is crucial that @{ML select_tac'} is prefixed with @{ML CHANGED}, |
|
857 because otherwise @{ML REPEAT} runs into an infinite loop. The function |
|
858 @{ML REPEAT1} is similar, but runs the tactic at least once (failing if |
|
859 this is not possible). |
|
860 |
|
861 If you are after the ``primed'' version of @{ML repeat_xmp} then it |
|
862 needs to be coded as |
|
863 *} |
|
864 |
|
865 ML{*val repeat_xmp' = REPEAT o CHANGED o select_tac'*} |
|
866 |
|
867 text {* |
|
868 since there are no ``primed'' versions of @{ML REPEAT} and @{ML CHANGED}. |
|
869 |
|
870 If you look closely at the goal state above, the tactics @{ML repeat_xmp} |
|
871 and @{ML repeat_xmp'} are not yet quite what we are after: the problem is |
|
872 that goals 2 and 3 are not yet analysed. This is because both tactics |
|
873 apply repeatedly only to the first subgoal. To analyse also all |
|
874 resulting subgoals, you can use the function @{ML REPEAT_ALL_NEW}. |
|
875 Suppose the tactic |
|
876 *} |
|
877 |
|
878 ML{*val repeat_all_new_xmp = REPEAT_ALL_NEW (CHANGED o select_tac')*} |
|
879 |
|
880 text {* |
|
881 which analyses the topmost connectives also in all resulting |
|
882 subgoals. |
|
883 *} |
|
884 |
|
885 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
|
886 apply(tactic {* repeat_all_new_xmp 1 *}) |
|
887 txt{* \begin{minipage}{\textwidth} |
|
888 @{subgoals [display]} |
|
889 \end{minipage} *} |
|
890 (*<*)oops(*>*) |
|
891 |
|
892 text {* |
|
893 The last tactic combinator we describe here is @{ML DETERM}. Recall |
|
894 that tactics produce a lazy sequence of successor goal states. These |
|
895 states can be explored using the command \isacommand{back}. For example |
|
896 |
|
897 *} |
|
898 |
|
899 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
|
900 apply(tactic {* etac @{thm disjE} 1 *}) |
|
901 txt{* applies the rule to the first assumption |
|
902 |
|
903 \begin{minipage}{\textwidth} |
|
904 @{subgoals [display]} |
|
905 \end{minipage} *} |
|
906 (*<*) |
|
907 oops |
|
908 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
|
909 apply(tactic {* etac @{thm disjE} 1 *}) |
|
910 (*>*) |
|
911 back |
|
912 txt{* whereas it is now applied to the second |
|
913 |
|
914 \begin{minipage}{\textwidth} |
|
915 @{subgoals [display]} |
|
916 \end{minipage} *} |
|
917 (*<*)oops(*>*) |
|
918 |
|
919 text {* |
|
920 Sometimes this leads to confusing behaviour of tactics and also has |
|
921 the potential to explode the search space for tactics build on top. |
|
922 This can be avoided by prefixing the tactic with @{ML DETERM}. |
|
923 *} |
|
924 |
|
925 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
|
926 apply(tactic {* DETERM (etac @{thm disjE} 1) *}) |
|
927 txt {*\begin{minipage}{\textwidth} |
|
928 @{subgoals [display]} |
|
929 \end{minipage} *} |
|
930 (*<*)oops(*>*) |
|
931 text {* |
|
932 This will prune the search space to just the first possibility. |
|
933 Attempting to apply \isacommand{back} in this goal states gives the |
|
934 error message: |
|
935 |
|
936 \begin{isabelle} |
|
937 @{text "*** back: no alternatives"}\\ |
|
938 @{text "*** At command \"back\"."} |
|
939 \end{isabelle} |
|
940 |
|
941 \begin{readmore} |
|
942 Most tactic combinators are defined in @{ML_file "Pure/tctical.ML"}. |
|
943 \end{readmore} |
817 |
944 |
818 *} |
945 *} |
819 |
946 |
820 section {* Rewriting and Simplifier Tactics *} |
947 section {* Rewriting and Simplifier Tactics *} |
821 |
948 |