135 hard-coded inside the tactic. For most operators that combine tactics |
135 hard-coded inside the tactic. For most operators that combine tactics |
136 (@{ML THEN} is only one such operator) a ``primed'' version exists. |
136 (@{ML THEN} is only one such operator) a ``primed'' version exists. |
137 |
137 |
138 The tactics @{ML foo_tac} and @{ML foo_tac'} are very specific for |
138 The tactics @{ML foo_tac} and @{ML foo_tac'} are very specific for |
139 analysing goals being only of the form @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. If the goal is not |
139 analysing goals being only of the form @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. If the goal is not |
140 of this form, then they throw the error message: |
140 of this form, then they return the error message: |
141 |
141 |
142 \begin{isabelle} |
142 \begin{isabelle} |
143 @{text "*** empty result sequence -- proof command failed"}\\ |
143 @{text "*** empty result sequence -- proof command failed"}\\ |
144 @{text "*** At command \"apply\"."} |
144 @{text "*** At command \"apply\"."} |
145 \end{isabelle} |
145 \end{isabelle} |
146 |
146 |
147 Meaning the tactics failed. The reason for this error message is that tactics |
147 This means the tactics failed. The reason for this error message is that tactics |
148 are functions that map a goal state to a (lazy) sequence of successor states, |
148 are functions mapping a goal state to a (lazy) sequence of successor states. |
149 hence the type of a tactic is: |
149 Hence the type of a tactic is: |
|
150 *} |
150 |
151 |
151 @{text [display, gray] "type tactic = thm -> thm Seq.seq"} |
152 ML{*type tactic = thm -> thm Seq.seq*} |
152 |
153 |
153 It is custom that if a tactic fails, it should return the empty sequence: |
154 text {* |
154 therefore your own tactics should not raise exceptions willy-nilly. Only |
155 By convention, if a tactic fails, then it should return the empty sequence. |
155 in very grave failure situations should a tactic raise the exception |
156 Therefore, if you write your own tactics, they should not raise exceptions |
156 @{text THM}. |
157 willy-nilly; only in very grave failure situations should a tactic raise the |
|
158 exception @{text THM}. |
157 |
159 |
158 The simplest tactics are @{ML no_tac} and @{ML all_tac}. The first returns |
160 The simplest tactics are @{ML no_tac} and @{ML all_tac}. The first returns |
159 the empty sequence and is defined as |
161 the empty sequence and is defined as |
160 *} |
162 *} |
161 |
163 |
162 ML{*fun no_tac thm = Seq.empty*} |
164 ML{*fun no_tac thm = Seq.empty*} |
163 |
165 |
164 text {* |
166 text {* |
165 which means @{ML no_tac} always fails. The second returns the given theorem wrapped |
167 which means @{ML no_tac} always fails. The second returns the given theorem wrapped |
166 as a single member sequence; @{ML all_tac} is defined as |
168 up in a single member sequence; it is defined as |
167 *} |
169 *} |
168 |
170 |
169 ML{*fun all_tac thm = Seq.single thm*} |
171 ML{*fun all_tac thm = Seq.single thm*} |
170 |
172 |
171 text {* |
173 text {* |
172 which means it always succeeds (but also does not make any progress |
174 which means @{ML all_tac} always succeeds, but also does not make any progress |
173 with the proof). |
175 with the proof. |
174 |
176 |
175 The lazy list of possible successor states shows through at the user-level |
177 The lazy list of possible successor goal states shows through at the user-level |
176 of Isabelle when using the command \isacommand{back}. For instance in the |
178 of Isabelle when using the command \isacommand{back}. For instance in the |
177 following proof there are two possibilities for how to apply |
179 following proof there are two possibilities for how to apply |
178 @{ML foo_tac'}: either using the first assumption or the second. |
180 @{ML foo_tac'}: either using the first assumption or the second. |
179 *} |
181 *} |
180 |
182 |
209 val _ = warning (str_of_thm ctxt thm) |
212 val _ = warning (str_of_thm ctxt thm) |
210 in |
213 in |
211 Seq.single thm |
214 Seq.single thm |
212 end*} |
215 end*} |
213 |
216 |
214 text {* |
217 text_raw {* |
215 which prints out the given theorem (using the string-function defined |
218 \begin{figure}[p] |
216 in Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. We |
219 \begin{isabelle} |
217 are now in the position to inspect every goal state in a proof. Consider |
220 *} |
218 the proof below: on the left-hand side we show the goal state as shown |
|
219 by Isabelle, on the right-hand side the print out from @{ML my_print_tac}. |
|
220 *} |
|
221 |
|
222 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B" |
221 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B" |
223 apply(tactic {* my_print_tac @{context} *}) |
222 apply(tactic {* my_print_tac @{context} *}) |
224 |
223 |
225 txt{* \small |
224 txt{* \begin{minipage}{\textwidth} |
226 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
|
227 \begin{minipage}[t]{0.3\textwidth} |
|
228 @{subgoals [display]} |
225 @{subgoals [display]} |
229 \end{minipage} & |
226 \end{minipage}\medskip |
|
227 |
|
228 \begin{minipage}{\textwidth} |
|
229 \small\colorbox{gray!20}{ |
|
230 \begin{tabular}{@ {}l@ {}} |
|
231 internal goal state:\\ |
230 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
232 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
231 \end{tabularstar} |
233 \end{tabular}} |
|
234 \end{minipage}\medskip |
232 *} |
235 *} |
233 |
236 |
234 apply(rule conjI) |
237 apply(rule conjI) |
235 apply(tactic {* my_print_tac @{context} *}) |
238 apply(tactic {* my_print_tac @{context} *}) |
236 |
239 |
237 txt{* \small |
240 txt{* \begin{minipage}{\textwidth} |
238 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
|
239 \begin{minipage}[t]{0.26\textwidth} |
|
240 @{subgoals [display]} |
241 @{subgoals [display]} |
241 \end{minipage} & |
242 \end{minipage}\medskip |
|
243 |
|
244 \begin{minipage}{\textwidth} |
|
245 \small\colorbox{gray!20}{ |
|
246 \begin{tabular}{@ {}l@ {}} |
|
247 internal goal state:\\ |
242 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
248 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
243 \end{tabularstar} |
249 \end{tabular}} |
|
250 \end{minipage}\medskip |
244 *} |
251 *} |
245 |
252 |
246 apply(assumption) |
253 apply(assumption) |
247 apply(tactic {* my_print_tac @{context} *}) |
254 apply(tactic {* my_print_tac @{context} *}) |
248 |
255 |
249 txt{* \small |
256 txt{* \begin{minipage}{\textwidth} |
250 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
|
251 \begin{minipage}[t]{0.3\textwidth} |
|
252 @{subgoals [display]} |
257 @{subgoals [display]} |
253 \end{minipage} & |
258 \end{minipage}\medskip |
|
259 |
|
260 \begin{minipage}{\textwidth} |
|
261 \small\colorbox{gray!20}{ |
|
262 \begin{tabular}{@ {}l@ {}} |
|
263 internal goal state:\\ |
254 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
264 @{text "(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> B) \<Longrightarrow> (\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B)"} |
255 \end{tabularstar} |
265 \end{tabular}} |
|
266 \end{minipage}\medskip |
256 *} |
267 *} |
257 |
268 |
258 apply(assumption) |
269 apply(assumption) |
259 apply(tactic {* my_print_tac @{context} *}) |
270 apply(tactic {* my_print_tac @{context} *}) |
260 |
271 |
261 txt{* \small |
272 txt{* \begin{minipage}{\textwidth} |
262 \begin{tabularstar}{\textwidth}{@ {}l@ {\extracolsep{\fill}}l@ {}} |
|
263 \begin{minipage}[t]{0.3\textwidth} |
|
264 @{subgoals [display]} |
273 @{subgoals [display]} |
265 \end{minipage} & |
274 \end{minipage}\medskip |
|
275 |
|
276 \begin{minipage}{\textwidth} |
|
277 \small\colorbox{gray!20}{ |
|
278 \begin{tabular}{@ {}l@ {}} |
|
279 internal goal state:\\ |
266 @{text "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"} |
280 @{text "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"} |
267 \end{tabularstar} |
281 \end{tabular}} |
268 *} |
282 \end{minipage}\medskip |
269 |
283 *} |
270 done |
284 done |
271 |
285 text_raw {* |
272 text {* |
286 \end{isabelle} |
273 As can be seen, internally every goal state is an implication of the form |
287 \caption{A proof where we show the goal state as printed |
|
288 by the Isabelle system and as represented internally |
|
289 (highlighted boxes).\label{fig:goalstates}} |
|
290 \end{figure} |
|
291 *} |
|
292 |
|
293 |
|
294 text {* |
|
295 which prints out the given theorem (using the string-function defined in |
|
296 Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. With this |
|
297 tactic we are in the position to inspect every goal state in a |
|
298 proof. Consider now the proof in Figure~\ref{fig:goalstates}: as can be seen, |
|
299 internally every goal state is an implication of the form |
274 |
300 |
275 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
301 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
276 |
302 |
277 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the |
303 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are |
278 subgoals. So after setting up the lemma, the goal state is always of the form |
304 the subgoals. So after setting up the lemma, the goal state is always of the |
279 @{text "C \<Longrightarrow> (C)"}; when the proof is finished we are left with @{text "(C)"}. |
305 form @{text "C \<Longrightarrow> (C)"}; when the proof is finished we are left with @{text |
280 Since the goal @{term C} can potentially be an implication, |
306 "(C)"}. Since the goal @{term C} can potentially be an implication, there is |
281 there is a ``protector'' wrapped around it (in from of an outermost constant |
307 a ``protector'' wrapped around it (in from of an outermost constant @{text |
282 @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal; |
308 "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal; however this constant |
283 however this constant is invisible in the print out above). This |
309 is invisible in the figure). This prevents that premises of @{text C} are |
284 prevents that premises of @{text C} are mis-interpreted as open subgoals. |
310 mis-interpreted as open subgoals. While tactics can operate on the subgoals |
285 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
311 (the @{text "A\<^isub>i"} above), they are expected to leave the conclusion |
286 are expected to leave the conclusion @{term C} intact, with the |
312 @{term C} intact, with the exception of possibly instantiating schematic |
287 exception of possibly instantiating schematic variables. If you use |
313 variables. If you use the predefined tactics, which we describe in the next |
288 the predefined tactics, this will always be the case. |
314 section, this will always be the case. |
289 |
315 |
290 \begin{readmore} |
316 \begin{readmore} |
291 For more information about the internals of goals see \isccite{sec:tactical-goals}. |
317 For more information about the internals of goals see \isccite{sec:tactical-goals}. |
292 \end{readmore} |
318 \end{readmore} |
293 |
319 |
294 *} |
320 *} |
295 |
321 |
296 section {* Simple Tactics *} |
322 section {* Simple Tactics *} |
297 |
323 |
298 text {* |
324 text {* |
299 A simple tactic is @{ML print_tac}, which is quite useful for low-level debugging of tactics. |
325 Let us start with the tactic @{ML print_tac}, which is quite useful for low-level |
300 It just prints out a message and the current goal state. |
326 debugging of tactics. It just prints out a message and the current goal state. |
|
327 Processing the proof |
301 *} |
328 *} |
302 |
329 |
303 lemma shows "False \<Longrightarrow> True" |
330 lemma shows "False \<Longrightarrow> True" |
304 apply(tactic {* print_tac "foo message" *}) |
331 apply(tactic {* print_tac "foo message" *}) |
305 txt{*\begin{minipage}{\textwidth}\small |
332 txt{*gives:\medskip |
|
333 |
|
334 \begin{minipage}{\textwidth}\small |
306 @{text "foo message"}\\[3mm] |
335 @{text "foo message"}\\[3mm] |
307 @{prop "False \<Longrightarrow> True"}\\ |
336 @{prop "False \<Longrightarrow> True"}\\ |
308 @{text " 1. False \<Longrightarrow> True"}\\ |
337 @{text " 1. False \<Longrightarrow> True"}\\ |
309 \end{minipage} |
338 \end{minipage} |
310 *} |
339 *} |
411 @{subgoals [display]} |
448 @{subgoals [display]} |
412 \end{minipage}*} |
449 \end{minipage}*} |
413 (*<*)oops(*>*) |
450 (*<*)oops(*>*) |
414 |
451 |
415 text {* |
452 text {* |
416 where the application of @{text bspec} results into two subgoals involving the |
453 where the application of Rule @{text bspec} generates two subgoals involving the |
417 meta-variable @{text "?x"}. The point is that if you are not careful, tactics |
454 meta-variable @{text "?x"}. Now, if you are not careful, tactics |
418 applied to the first subgoal might instantiate this meta-variable in such a |
455 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"} |
456 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 |
457 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 |
458 constraint version of the @{text bspec}-rule. Such constraints can be given by |
422 pre-instantiating theorems with other theorems, for example by using the |
459 pre-instantiating theorems with other theorems. One function to do this is |
423 function @{ML RS} |
460 @{ML RS} |
424 |
461 |
425 @{ML_response_fake [display,gray] |
462 @{ML_response_fake [display,gray] |
426 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
463 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
427 |
464 |
428 which, for instance, instantiates the first premise of the @{text conjI}-rule |
465 which in the example instantiates the first premise of the @{text conjI}-rule |
429 with the rule @{text disjI1}. If this is impossible, as in the case of |
466 with the rule @{text disjI1}. If the instantiation is impossible, as in the |
|
467 case of |
430 |
468 |
431 @{ML_response_fake_both [display,gray] |
469 @{ML_response_fake_both [display,gray] |
432 "@{thm conjI} RS @{thm mp}" |
470 "@{thm conjI} RS @{thm mp}" |
433 "*** Exception- THM (\"RSN: no unifiers\", 1, |
471 "*** Exception- THM (\"RSN: no unifiers\", 1, |
434 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
472 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
435 |
473 |
436 the function raises an exception. The function @{ML RSN} is similar, but |
474 then the function raises an exception. The function @{ML RSN} is similar to @{ML RS}, but |
437 takes a number as argument and thus you can make explicit which premise |
475 takes an additional number as argument that makes explicit which premise |
438 should be instantiated. |
476 should be instantiated. |
439 |
477 |
440 To improve readability of the theorems we produce below, we shall use |
478 To improve readability of the theorems we produce below, we shall use |
441 the following function |
479 the following function |
442 *} |
480 *} |
534 \end{tabular} |
573 \end{tabular} |
535 \end{quote} |
574 \end{quote} |
536 |
575 |
537 Note in the actual output the brown colour of the variables @{term x} and |
576 Note in the actual output the brown colour of the variables @{term x} and |
538 @{term y}. Although they are parameters in the original goal, they are fixed inside |
577 @{term y}. Although they are parameters in the original goal, they are fixed inside |
539 the subproof. Similarly the schematic variable @{term z}. The assumption |
578 the subproof. By convention these fixed variables are printed in brown colour. |
|
579 Similarly the schematic variable @{term z}. The assumption, or premise, |
540 @{prop "A x y"} is bound as @{ML_type cterm} to the record-variable |
580 @{prop "A x y"} is bound as @{ML_type cterm} to the record-variable |
541 @{text asms} but also as @{ML_type thm} to @{text prems}. |
581 @{text asms}, but also as @{ML_type thm} to @{text prems}. |
542 |
582 |
543 Notice also that we had to append @{text "?"} to \isacommand{apply}. The |
583 Notice also that we had to append @{text [quotes] "?"} to the |
544 reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely. |
584 \isacommand{apply}-command. The reason is that @{ML SUBPROOF} normally |
545 Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof |
585 expects that the subgoal is solved completely. Since in the function @{ML |
546 obviously fails. The question-mark allows us to recover from this failure |
586 sp_tac} we returned the tactic @{ML no_tac}, the subproof obviously |
547 in a graceful manner so that the warning messages are not overwritten |
587 fails. The question-mark allows us to recover from this failure in a |
548 by an error message. |
588 graceful manner so that the warning messages are not overwritten by an |
|
589 ``empty sequence'' error message. |
549 |
590 |
550 If we continue the proof script by applying the @{text impI}-rule |
591 If we continue the proof script by applying the @{text impI}-rule |
551 *} |
592 *} |
552 |
593 |
553 apply(rule impI) |
594 apply(rule impI) |
554 apply(tactic {* SUBPROOF sp_tac @{context} 1 *})? |
595 apply(tactic {* SUBPROOF sp_tac @{context} 1 *})? |
555 |
596 |
556 txt {* |
597 txt {* |
557 then @{ML sp_tac} prints out |
598 then tactic prints out |
558 |
599 |
559 \begin{quote}\small |
600 \begin{quote}\small |
560 \begin{tabular}{ll} |
601 \begin{tabular}{ll} |
561 params: & @{term x}, @{term y}\\ |
602 params: & @{term x}, @{term y}\\ |
562 schematics: & @{term z}\\ |
603 schematics: & @{term z}\\ |
567 \end{quote} |
608 \end{quote} |
568 *} |
609 *} |
569 (*<*)oops(*>*) |
610 (*<*)oops(*>*) |
570 |
611 |
571 text {* |
612 text {* |
572 where we now also have @{term "B y x"} as an assumption. |
613 Now also @{term "B y x"} is an assumption bound to @{text asms} and @{text prems}. |
573 |
614 |
574 One convenience of @{ML SUBPROOF} is that we can apply the assumptions |
615 One convenience of @{ML SUBPROOF} is that we can apply the assumptions |
575 using the usual tactics, because the parameter @{text prems} |
616 using the usual tactics, because the parameter @{text prems} |
576 contains them as theorems. With this we can easily |
617 contains them as theorems. With this you can easily |
577 implement a tactic that almost behaves like @{ML atac}, namely: |
618 implement a tactic that behaves almost like @{ML atac}: |
578 *} |
619 *} |
579 |
620 |
580 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*} |
621 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*} |
581 |
622 |
582 text {* |
623 text {* |
583 If we apply it to the next lemma |
624 If you apply @{ML atac'} to the next lemma |
584 *} |
625 *} |
585 |
626 |
586 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
627 lemma shows "\<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
587 apply(tactic {* atac' @{context} 1 *}) |
628 apply(tactic {* atac' @{context} 1 *}) |
588 txt{* we get |
629 txt{* it will produce |
589 @{subgoals [display]} *} |
630 @{subgoals [display]} *} |
590 (*<*)oops(*>*) |
631 (*<*)oops(*>*) |
591 |
632 |
592 text {* |
633 text {* |
593 The restriction in this tactic is that it cannot instantiate any |
634 The restriction in this tactic which is not present in @{ML atac} is |
|
635 that it cannot instantiate any |
594 schematic variable. This might be seen as a defect, but it is actually |
636 schematic variable. This might be seen as a defect, but it is actually |
595 an advantage in the situations for which @{ML SUBPROOF} was designed: |
637 an advantage in the situations for which @{ML SUBPROOF} was designed: |
596 the reason is that instantiation of schematic variables can affect |
638 the reason is that, as mentioned before, instantiation of schematic variables can affect |
597 several goals and can render them unprovable. @{ML SUBPROOF} is meant |
639 several goals and can render them unprovable. @{ML SUBPROOF} is meant |
598 to avoid this. |
640 to avoid this. |
599 |
641 |
600 Notice that @{ML atac'} calls @{ML resolve_tac} with the subgoal |
642 Notice that @{ML atac'} inside @{ML SUBPROOF} calls @{ML resolve_tac} with |
601 number @{text "1"} and also the ``outer'' call to @{ML SUBPROOF} in |
643 the subgoal number @{text "1"} and also the outer call to @{ML SUBPROOF} in |
602 the \isacommand{apply}-step uses @{text "1"}. Another advantage |
644 the \isacommand{apply}-step uses @{text "1"}. This is another advantage |
603 of @{ML SUBGOAL} is that the addressing inside it is completely |
645 of @{ML SUBPROOF}: the addressing inside it is completely |
604 local to the subproof inside. It is therefore possible to also apply |
646 local to the tactic inside the subproof. It is therefore possible to also apply |
605 @{ML atac'} to the second goal by just writing: |
647 @{ML atac'} to the second goal by just writing: |
606 *} |
648 *} |
607 |
649 |
608 lemma shows "True" and "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
650 lemma shows "True" and "\<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
609 apply(tactic {* atac' @{context} 2 *}) |
651 apply(tactic {* atac' @{context} 2 *}) |
610 apply(rule TrueI) |
652 apply(rule TrueI) |
611 done |
653 done |
612 |
654 |
613 |
655 |
617 also described in \isccite{sec:results}. |
659 also described in \isccite{sec:results}. |
618 \end{readmore} |
660 \end{readmore} |
619 |
661 |
620 A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. |
662 A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. |
621 It allows you to inspect a given subgoal. With this you can implement |
663 It allows you to inspect a given subgoal. With this you can implement |
622 a tactic that applies a rule according to the topmost connective in the |
664 a tactic that applies a rule according to the topmost logic connective in the |
623 subgoal (to illustrate this we only analyse a few connectives). The code |
665 subgoal (to illustrate this we only analyse a few connectives). The code |
624 of this tactic is as follows.\label{tac:selecttac} |
666 of the tactic is as follows.\label{tac:selecttac} |
625 *} |
667 *} |
626 |
668 |
627 ML %linenumbers{*fun select_tac (t,i) = |
669 ML %linenumbers{*fun select_tac (t,i) = |
628 case t of |
670 case t of |
629 @{term "Trueprop"} $ t' => select_tac (t',i) |
671 @{term "Trueprop"} $ t' => select_tac (t',i) |
|
672 | @{term "op \<Longrightarrow>"} $ _ $ t' => select_tac (t',i) |
630 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
673 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
631 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
674 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
632 | @{term "Not"} $ _ => rtac @{thm notI} i |
675 | @{term "Not"} $ _ => rtac @{thm notI} i |
633 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
676 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
634 | _ => all_tac*} |
677 | _ => all_tac*} |
635 |
678 |
636 text {* |
679 text {* |
637 In line 3 you need to descend under the outermost @{term "Trueprop"} in order |
680 The input of the function is a term representing the subgoal and a number |
638 to get to the connective you like to analyse. Otherwise goals like @{prop "A \<and> B"} |
681 specifying the subgoal of interest. In line 3 you need to descend under the |
639 are not properly analysed. While for the first four pattern we can use the |
682 outermost @{term "Trueprop"} in order to get to the connective you like to |
640 @{text "@term"}-antiquotation, the pattern in Line 7 cannot be constructed |
683 analyse. Otherwise goals like @{prop "A \<and> B"} are not properly |
641 in this way. The reason is that an antiquotation would fix the type of the |
684 analysed. Similarly with meta-implications in the next line. While for the |
642 quantified variable. So you really have to construct the pattern |
685 first five patterns we can use the @{text "@term"}-antiquotation to |
643 using the term-constructors. This is not necessary in other cases, because |
686 construct the patterns, the pattern in Line 8 cannot be constructed in this |
644 their type is always something involving @{typ bool}. The final patter is |
687 way. The reason is that an antiquotation would fix the type of the |
645 for the case where the goal does not fall into any of the categories before. |
688 quantified variable. So you really have to construct the pattern using the |
646 In this case we chose to just return @{ML all_tac} (i.e., @{ML select_tac} |
689 basic term-constructors. This is not necessary in other cases, because their type |
647 never fails). |
690 is always fixed to function types involving only the type @{typ bool}. The |
|
691 final pattern, we chose to just return @{ML all_tac}. Consequently, |
|
692 @{ML select_tac} never fails. |
648 |
693 |
649 Let us now see how to apply this tactic. Consider the four goals: |
694 Let us now see how to apply this tactic. Consider the four goals: |
650 *} |
695 *} |
651 |
696 |
652 |
697 |
660 \end{minipage} *} |
705 \end{minipage} *} |
661 (*<*)oops(*>*) |
706 (*<*)oops(*>*) |
662 |
707 |
663 text {* |
708 text {* |
664 where in all but the last the tactic applied an introduction rule. |
709 where in all but the last the tactic applied an introduction rule. |
665 Note that we applied the tactic to subgoals in ``reverse'' order. |
710 Note that we applied the tactic to the goals in ``reverse'' order. |
666 This is a trick in order to be independent from what subgoals are |
711 This is a trick in order to be independent from the subgoals that are |
667 that are produced by the rule. If we had applied it in the other order |
712 produced by the rule. If we had applied it in the other order |
668 *} |
713 *} |
669 |
714 |
670 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
715 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
671 apply(tactic {* SUBGOAL select_tac 1 *}) |
716 apply(tactic {* SUBGOAL select_tac 1 *}) |
672 apply(tactic {* SUBGOAL select_tac 3 *}) |
717 apply(tactic {* SUBGOAL select_tac 3 *}) |
673 apply(tactic {* SUBGOAL select_tac 4 *}) |
718 apply(tactic {* SUBGOAL select_tac 4 *}) |
674 apply(tactic {* SUBGOAL select_tac 5 *}) |
719 apply(tactic {* SUBGOAL select_tac 5 *}) |
675 (*<*)oops(*>*) |
720 (*<*)oops(*>*) |
676 |
721 |
677 text {* |
722 text {* |
678 then we have to be careful to not apply the tactic to the two subgoals the |
723 then we have to be careful to not apply the tactic to the two subgoals produced by |
679 first goal produced. To do this can result in quite messy code. In contrast, |
724 the first goal. To do this can result in quite messy code. In contrast, |
680 the ``reverse application'' is easy to implement. |
725 the ``reverse application'' is easy to implement. |
681 |
726 |
682 However, this example is very contrived: there are much simpler methods to implement |
727 Of course, this example is contrived: there are much simpler methods available in |
683 such a proof procedure analysing a goal according to its topmost |
728 Isabelle for implementing a proof procedure analysing a goal according to its topmost |
684 connective. These simpler methods use tactic combinators which will be explained |
729 connective. These simpler methods use tactic combinators, which we will explain |
685 in the next section. |
730 in the next section. |
686 *} |
731 *} |
687 |
732 |
688 section {* Tactic Combinators *} |
733 section {* Tactic Combinators *} |
689 |
734 |
690 text {* |
735 text {* |
691 The purpose of tactic combinators is to build powerful tactics out of |
736 The purpose of tactic combinators is to build compound tactics out of |
692 smaller components. In the previous section we already used @{ML THEN}, which |
737 smaller tactics. In the previous section we already used @{ML THEN}, which |
693 strings two tactics together in sequence. For example: |
738 just strings together two tactics in a sequence. For example: |
694 *} |
739 *} |
695 |
740 |
696 lemma shows "(Foo \<and> Bar) \<and> False" |
741 lemma shows "(Foo \<and> Bar) \<and> False" |
697 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
742 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
698 txt {* \begin{minipage}{\textwidth} |
743 txt {* \begin{minipage}{\textwidth} |
711 @{subgoals [display]} |
756 @{subgoals [display]} |
712 \end{minipage} *} |
757 \end{minipage} *} |
713 (*<*)oops(*>*) |
758 (*<*)oops(*>*) |
714 |
759 |
715 text {* |
760 text {* |
|
761 Here you only have to specify the subgoal of interest only once and |
|
762 it is consistently applied to the component tactics. |
716 For most tactic combinators such a ``primed'' version exists and |
763 For most tactic combinators such a ``primed'' version exists and |
717 in what follows we will usually prefer it over the ``unprimed'' one. |
764 in what follows we will usually prefer it over the ``unprimed'' one. |
718 |
765 |
719 If there is a list of tactics that should all be tried out in |
766 If there is a list of tactics that should all be tried out in |
720 sequence, you can use the combinator @{ML EVERY'}. For example |
767 sequence, you can use the combinator @{ML EVERY'}. For example |
721 the function @{ML foo_tac'} from page~\ref{tac:footacprime} can also |
768 the function @{ML foo_tac'} from page~\pageref{tac:footacprime} can also |
722 be written as: |
769 be written as: |
723 *} |
770 *} |
724 |
771 |
725 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
772 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
726 atac, rtac @{thm disjI1}, atac]*} |
773 atac, rtac @{thm disjI1}, atac]*} |
727 |
774 |
728 text {* |
775 text {* |
729 There is even another way: in automatic proof procedures (in contrast to |
776 There is even another way of implementing this tactic: in automatic proof |
730 tactics that might be called by the user) there are often long lists of |
777 procedures (in contrast to tactics that might be called by the user) there |
731 tactics that are applied to the first subgoal. Instead of writing the code |
778 are often long lists of tactics that are applied to the first |
732 above and then calling @{ML "foo_tac'' 1"}, you can also just write |
779 subgoal. Instead of writing the code above and then calling @{ML "foo_tac'' 1"}, |
|
780 you can also just write |
733 *} |
781 *} |
734 |
782 |
735 ML{*val foo_tac1 = EVERY1 [etac @{thm disjE}, rtac @{thm disjI2}, |
783 ML{*val foo_tac1 = EVERY1 [etac @{thm disjE}, rtac @{thm disjI2}, |
736 atac, rtac @{thm disjI1}, atac]*} |
784 atac, rtac @{thm disjI1}, atac]*} |
737 |
785 |
738 text {* |
786 text {* |
739 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML EVERY1} it must be |
787 and just call @{ML foo_tac1}. |
740 guaranteed that all component tactics successfully apply; otherwise the |
788 |
741 whole tactic will fail. If you rather want to try out a number of tactics, |
789 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML EVERY1} it must be |
742 then you can use the combinator @{ML ORELSE'} for two tactics, and @{ML FIRST'} |
790 guaranteed that all component tactics successfully apply; otherwise the |
743 (or @{ML FIRST1}) for a list of tactics. For example, the tactic |
791 whole tactic will fail. If you rather want to try out a number of tactics, |
|
792 then you can use the combinator @{ML ORELSE'} for two tactics, and @{ML |
|
793 FIRST'} (or @{ML FIRST1}) for a list of tactics. For example, the tactic |
|
794 |
744 *} |
795 *} |
745 |
796 |
746 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*} |
797 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*} |
747 |
798 |
748 text {* |
799 text {* |
749 will first try out whether rule @{text disjI} applies and after that |
800 will first try out whether rule @{text disjI} applies and after that |
750 whether @{text conjI}. To see this consider the proof: |
801 @{text conjI}. To see this consider the proof |
751 *} |
802 *} |
752 |
803 |
753 lemma shows "True \<and> False" and "Foo \<or> Bar" |
804 lemma shows "True \<and> False" and "Foo \<or> Bar" |
754 apply(tactic {* orelse_xmp 2 *}) |
805 apply(tactic {* orelse_xmp 2 *}) |
755 apply(tactic {* orelse_xmp 1 *}) |
806 apply(tactic {* orelse_xmp 1 *}) |
786 @{subgoals [display]} |
838 @{subgoals [display]} |
787 \end{minipage} *} |
839 \end{minipage} *} |
788 (*<*)oops(*>*) |
840 (*<*)oops(*>*) |
789 |
841 |
790 text {* |
842 text {* |
791 Because such repeated applications of a tactic to the reverse order of |
843 Since such repeated applications of a tactic to the reverse order of |
792 \emph{all} subgoals is quite common, there is the tactics combinator |
844 \emph{all} subgoals is quite common, there is the tactic combinator |
793 @{ML ALLGOALS} that simplifies this. Using this combinator we can simply |
845 @{ML ALLGOALS} that simplifies this. Using this combinator you can simply |
794 write: *} |
846 write: *} |
795 |
847 |
796 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
848 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F" |
797 apply(tactic {* ALLGOALS select_tac' *}) |
849 apply(tactic {* ALLGOALS select_tac' *}) |
798 txt{* \begin{minipage}{\textwidth} |
850 txt{* \begin{minipage}{\textwidth} |
799 @{subgoals [display]} |
851 @{subgoals [display]} |
800 \end{minipage} *} |
852 \end{minipage} *} |
801 (*<*)oops(*>*) |
853 (*<*)oops(*>*) |
802 |
854 |
803 text {* |
855 text {* |
804 Remember that we chose to write @{ML select_tac'} in such a way that it always |
856 Remember that we chose to implement @{ML select_tac'} so that it |
805 succeeds. This can be potentially very confusing for the user, for example, |
857 always succeeds. This can be potentially very confusing for the user, |
806 in cases the goals is the form |
858 for example, in cases where the goal is the form |
807 *} |
859 *} |
808 |
860 |
809 lemma shows "E \<Longrightarrow> F" |
861 lemma shows "E \<Longrightarrow> F" |
810 apply(tactic {* select_tac' 1 *}) |
862 apply(tactic {* select_tac' 1 *}) |
811 txt{* \begin{minipage}{\textwidth} |
863 txt{* \begin{minipage}{\textwidth} |
812 @{subgoals [display]} |
864 @{subgoals [display]} |
813 \end{minipage} *} |
865 \end{minipage} *} |
814 (*<*)oops(*>*) |
866 (*<*)oops(*>*) |
815 |
867 |
816 text {* |
868 text {* |
817 where no rule applies. The reason is that the user has little chance |
869 In this case no rule applies. The problem for the user is that there is little |
818 to see whether progress in the proof has been made or not. We could simply |
870 chance to see whether or not progress in the proof has been made. By convention |
819 delete th @{ML "K all_tac"} from the end of the list. Then @{ML select_tac'} |
871 therefore, tactics visible to the user should either change something or fail. |
820 would only succeed on goals where it can make progress. But for the sake of |
872 |
821 argument, let us suppose that this deletion is not an option. In such cases, you |
873 To comply with this convention, we could simply delete the @{ML "K all_tac"} |
822 can use the combinator @{ML CHANGED} to make sure the subgoal has been |
874 from the end of the theorem list. As a result @{ML select_tac'} would only |
823 changed by the tactic. Because now |
875 succeed on goals where it can make progress. But for the sake of argument, |
|
876 let us suppose that this deletion is \emph{not} an option. In such cases, you can |
|
877 use the combinator @{ML CHANGED} to make sure the subgoal has been changed |
|
878 by the tactic. Because now |
|
879 |
824 *} |
880 *} |
825 |
881 |
826 lemma shows "E \<Longrightarrow> F" |
882 lemma shows "E \<Longrightarrow> F" |
827 apply(tactic {* CHANGED (select_tac' 1) *})(*<*)?(*>*) |
883 apply(tactic {* CHANGED (select_tac' 1) *})(*<*)?(*>*) |
828 txt{* results in the error message: |
884 txt{* gives the error message: |
829 \begin{isabelle} |
885 \begin{isabelle} |
830 @{text "*** empty result sequence -- proof command failed"}\\ |
886 @{text "*** empty result sequence -- proof command failed"}\\ |
831 @{text "*** At command \"apply\"."} |
887 @{text "*** At command \"apply\"."} |
832 \end{isabelle} |
888 \end{isabelle} |
833 *}(*<*)oops(*>*) |
889 *}(*<*)oops(*>*) |
834 |
890 |
835 |
891 |
836 text {* |
892 text {* |
837 Meaning the tactic failed. |
893 We can further extend @{ML select_tac'} so that it not just applies to the topmost |
838 |
894 connective, but also to the ones immediately ``underneath'', i.e.~analyse the goal |
839 We can extend @{ML select_tac'} so that it not just applies to the top-most |
895 completely. For this you can use the tactic combinator @{ML REPEAT}. As an example |
840 connective, but also to the ones immediately ``underneath''. For this you can use the |
896 suppose the following tactic |
841 tactic combinator @{ML REPEAT}. For example suppose the following tactic |
|
842 *} |
897 *} |
843 |
898 |
844 ML{*val repeat_xmp = REPEAT (CHANGED (select_tac' 1)) *} |
899 ML{*val repeat_xmp = REPEAT (CHANGED (select_tac' 1)) *} |
845 |
900 |
846 text {* and the proof *} |
901 text {* which applied to the proof *} |
847 |
902 |
848 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
903 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
849 apply(tactic {* repeat_xmp *}) |
904 apply(tactic {* repeat_xmp *}) |
850 txt{* \begin{minipage}{\textwidth} |
905 txt{* produces |
|
906 |
|
907 \begin{minipage}{\textwidth} |
851 @{subgoals [display]} |
908 @{subgoals [display]} |
852 \end{minipage} *} |
909 \end{minipage} *} |
853 (*<*)oops(*>*) |
910 (*<*)oops(*>*) |
854 |
911 |
855 text {* |
912 text {* |
856 Here it is crucial that @{ML select_tac'} is prefixed with @{ML CHANGED}, |
913 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 |
914 because otherwise @{ML REPEAT} runs into an infinite loop (it applies the |
|
915 tactic as long as it succeeds). The function |
858 @{ML REPEAT1} is similar, but runs the tactic at least once (failing if |
916 @{ML REPEAT1} is similar, but runs the tactic at least once (failing if |
859 this is not possible). |
917 this is not possible). |
860 |
918 |
861 If you are after the ``primed'' version of @{ML repeat_xmp} then it |
919 If you are after the ``primed'' version of @{ML repeat_xmp} then you |
862 needs to be coded as |
920 need to implement it as |
863 *} |
921 *} |
864 |
922 |
865 ML{*val repeat_xmp' = REPEAT o CHANGED o select_tac'*} |
923 ML{*val repeat_xmp' = REPEAT o CHANGED o select_tac'*} |
866 |
924 |
867 text {* |
925 text {* |
868 since there are no ``primed'' versions of @{ML REPEAT} and @{ML CHANGED}. |
926 since there are no ``primed'' versions of @{ML REPEAT} and @{ML CHANGED}. |
869 |
927 |
870 If you look closely at the goal state above, the tactics @{ML repeat_xmp} |
928 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 |
929 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 |
930 that goals 2 and 3 are not analysed. This is because the tactic |
873 apply repeatedly only to the first subgoal. To analyse also all |
931 is applied repeatedly only to the first subgoal. To analyse also all |
874 resulting subgoals, you can use the function @{ML REPEAT_ALL_NEW}. |
932 resulting subgoals, you can use the tactic combinator @{ML REPEAT_ALL_NEW}. |
875 Suppose the tactic |
933 Suppose the tactic |
876 *} |
934 *} |
877 |
935 |
878 ML{*val repeat_all_new_xmp = REPEAT_ALL_NEW (CHANGED o select_tac')*} |
936 ML{*val repeat_all_new_xmp = REPEAT_ALL_NEW (CHANGED o select_tac')*} |
879 |
937 |
880 text {* |
938 text {* |
881 which analyses the topmost connectives also in all resulting |
939 you see that the following goal |
882 subgoals. |
|
883 *} |
940 *} |
884 |
941 |
885 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
942 lemma shows "((\<not>A) \<and> (\<forall>x. B x)) \<and> (C \<longrightarrow> D)" |
886 apply(tactic {* repeat_all_new_xmp 1 *}) |
943 apply(tactic {* repeat_all_new_xmp 1 *}) |
887 txt{* \begin{minipage}{\textwidth} |
944 txt{* \begin{minipage}{\textwidth} |
888 @{subgoals [display]} |
945 @{subgoals [display]} |
889 \end{minipage} *} |
946 \end{minipage} *} |
890 (*<*)oops(*>*) |
947 (*<*)oops(*>*) |
891 |
948 |
892 text {* |
949 text {* |
893 The last tactic combinator we describe here is @{ML DETERM}. Recall |
950 is completely analysed according to the theorems we chose to |
894 that tactics produce a lazy sequence of successor goal states. These |
951 include in @{ML select_tac}. |
|
952 |
|
953 Recall that tactics produce a lazy sequence of successor goal states. These |
895 states can be explored using the command \isacommand{back}. For example |
954 states can be explored using the command \isacommand{back}. For example |
896 |
955 |
897 *} |
956 *} |
898 |
957 |
899 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
958 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
900 apply(tactic {* etac @{thm disjE} 1 *}) |
959 apply(tactic {* etac @{thm disjE} 1 *}) |
901 txt{* applies the rule to the first assumption |
960 txt{* applies the rule to the first assumption yielding the goal state:\smallskip |
902 |
961 |
903 \begin{minipage}{\textwidth} |
962 \begin{minipage}{\textwidth} |
904 @{subgoals [display]} |
963 @{subgoals [display]} |
905 \end{minipage} *} |
964 \end{minipage}\smallskip |
|
965 |
|
966 After typing |
|
967 *} |
906 (*<*) |
968 (*<*) |
907 oops |
969 oops |
908 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
970 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
909 apply(tactic {* etac @{thm disjE} 1 *}) |
971 apply(tactic {* etac @{thm disjE} 1 *}) |
910 (*>*) |
972 (*>*) |
911 back |
973 back |
912 txt{* whereas it is now applied to the second |
974 txt{* the rule now applies to the second assumption.\smallskip |
913 |
975 |
914 \begin{minipage}{\textwidth} |
976 \begin{minipage}{\textwidth} |
915 @{subgoals [display]} |
977 @{subgoals [display]} |
916 \end{minipage} *} |
978 \end{minipage} *} |
917 (*<*)oops(*>*) |
979 (*<*)oops(*>*) |
918 |
980 |
919 text {* |
981 text {* |
920 Sometimes this leads to confusing behaviour of tactics and also has |
982 Sometimes this leads to confusing behaviour of tactics and also has |
921 the potential to explode the search space for tactics build on top. |
983 the potential to explode the search space for tactics. |
922 This can be avoided by prefixing the tactic with @{ML DETERM}. |
984 These problems can be avoided by prefixing the tactic with the tactic |
|
985 combinator @{ML DETERM}. |
923 *} |
986 *} |
924 |
987 |
925 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
988 lemma "\<lbrakk>P1 \<or> Q1; P2 \<or> Q2\<rbrakk> \<Longrightarrow> R" |
926 apply(tactic {* DETERM (etac @{thm disjE} 1) *}) |
989 apply(tactic {* DETERM (etac @{thm disjE} 1) *}) |
927 txt {*\begin{minipage}{\textwidth} |
990 txt {*\begin{minipage}{\textwidth} |
928 @{subgoals [display]} |
991 @{subgoals [display]} |
929 \end{minipage} *} |
992 \end{minipage} *} |
930 (*<*)oops(*>*) |
993 (*<*)oops(*>*) |
931 text {* |
994 text {* |
932 This will prune the search space to just the first possibility. |
995 This will combinator prune the search space to just the first successful application. |
933 Attempting to apply \isacommand{back} in this goal states gives the |
996 Attempting to apply \isacommand{back} in this goal states gives the |
934 error message: |
997 error message: |
935 |
998 |
936 \begin{isabelle} |
999 \begin{isabelle} |
937 @{text "*** back: no alternatives"}\\ |
1000 @{text "*** back: no alternatives"}\\ |
938 @{text "*** At command \"back\"."} |
1001 @{text "*** At command \"back\"."} |
939 \end{isabelle} |
1002 \end{isabelle} |
940 |
1003 |
941 \begin{readmore} |
1004 \begin{readmore} |
942 Most tactic combinators are defined in @{ML_file "Pure/tctical.ML"}. |
1005 Most tactic combinators described in this section are defined in @{ML_file "Pure/tctical.ML"}. |
943 \end{readmore} |
1006 \end{readmore} |
944 |
1007 |
945 *} |
1008 *} |
946 |
1009 |
947 section {* Rewriting and Simplifier Tactics *} |
1010 section {* Rewriting and Simplifier Tactics *} |