CookBook/Tactical.thy
changeset 104 5dcad9348e4d
parent 102 5e309df58557
child 105 f49dc7e96235
equal deleted inserted replaced
103:fe10da5354a3 104:5dcad9348e4d
    98 lemma "P \<or> Q \<Longrightarrow> Q \<or> P"
    98 lemma "P \<or> Q \<Longrightarrow> Q \<or> P"
    99 apply(tactic {* foo_tac *})
    99 apply(tactic {* foo_tac *})
   100 done
   100 done
   101 
   101 
   102 text {*
   102 text {*
   103   By using @{text "tactic \<verbopen> \<dots> \<verbclose>"} in the apply-step,
   103   By using @{text "tactic \<verbopen> \<dots> \<verbclose>"} you can call from the 
   104   you can call from the user level of Isabelle the tactic @{ML foo_tac} or 
   104   user level of Isabelle the tactic @{ML foo_tac} or 
   105   any other function that returns a tactic.
   105   any other function that returns a tactic.
   106 
   106 
   107   The tactic @{ML foo_tac} is just a sequence of simple tactics stringed
   107   The tactic @{ML foo_tac} is just a sequence of simple tactics stringed
   108   together by @{ML THEN}. As can be seen, each simple tactic in @{ML foo_tac}
   108   together by @{ML THEN}. As can be seen, each simple tactic in @{ML foo_tac}
   109   has a hard-coded number that stands for the subgoal analysed by the
   109   has a hard-coded number that stands for the subgoal analysed by the
   194   sequences. However in day-to-day Isabelle programming, one rarely 
   194   sequences. However in day-to-day Isabelle programming, one rarely 
   195   constructs sequences explicitly, but uses the predefined functions
   195   constructs sequences explicitly, but uses the predefined functions
   196   instead.
   196   instead.
   197   \end{readmore}
   197   \end{readmore}
   198 
   198 
   199   For a beginner it might be surprising that tactics, which transform
   199   It might be surprising that tactics, which transform
   200   one proof state to the next, are functions from theorems to theorem 
   200   one proof state to the next, are functions from theorems to theorem 
   201   (sequences). The surprise resolves by knowing that every 
   201   (sequences). The surprise resolves by knowing that every 
   202   proof state is indeed a theorem. To shed more light on this,
   202   goal state is indeed a theorem. To shed more light on this,
   203   let us modify the code of @{ML all_tac} to obtain the following
   203   let us modify the code of @{ML all_tac} to obtain the following
   204   tactic
   204   tactic
   205 *}
   205 *}
   206 
   206 
   207 ML{*fun my_print_tac ctxt thm =
   207 ML{*fun my_print_tac ctxt thm =
   214 text {*
   214 text {*
   215   which prints out the given theorem (using the string-function defined 
   215   which prints out the given theorem (using the string-function defined 
   216   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
   217   now can inspect every proof state in the follwing proof. On the left-hand
   217   now can inspect every proof state in the follwing proof. On the left-hand
   218   side we show the goal state as shown by the system; on the right-hand
   218   side we show the goal state as shown by the system; on the right-hand
   219   side the print out from our @{ML my_print_tac}.
   219   side the print out from @{ML my_print_tac}.
   220 *}
   220 *}
   221 
   221 
   222 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"
   222 lemma shows "\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> B"
   223 apply(tactic {* my_print_tac @{context} *})
   223 apply(tactic {* my_print_tac @{context} *})
   224 
   224 
   273   As can be seen, internally every goal state is an implication of the form
   273   As can be seen, internally every goal state is an implication of the form
   274 
   274 
   275   @{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)"}
   276 
   276 
   277   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  
   278   subgoals. Since the goal @{term C} can potentially be an implication, 
   278   subgoals. So in the first step the goal state is always of the form
   279   there is a protector (invisible in the print out above) wrapped around 
   279   @{text "C \<Longrightarrow> (C)"}. Since the goal @{term C} can potentially be an implication, 
   280   it. This prevents that premises are misinterpreted as open subgoals. 
   280   there is a ``protector'' wrapped around it (in from of an outermost constant 
       
   281   @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal;
       
   282   however this constant is invisible in the print out above). This 
       
   283   prevents that premises are misinterpreted as open subgoals. 
   281   While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they 
   284   While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they 
   282   are expected to leave the conclusion @{term C} intact, with the 
   285   are expected to leave the conclusion @{term C} intact, with the 
   283   exception of possibly instantiating schematic variables. 
   286   exception of possibly instantiating schematic variables. 
   284  
   287  
   285 *}
   288 *}
   295 done
   298 done
   296 
   299 
   297 text {*
   300 text {*
   298   Similarly, @{ML rtac}, @{ML dtac}, @{ML etac} and @{ML ftac} correspond
   301   Similarly, @{ML rtac}, @{ML dtac}, @{ML etac} and @{ML ftac} correspond
   299   to @{text rule}, @{text drule}, @{text erule} and @{text frule}, 
   302   to @{text rule}, @{text drule}, @{text erule} and @{text frule}, 
   300   respectively. Below are three examples with the resulting goal state. How
   303   respectively. Each of them takes a theorem as argument. Below are three 
   301   they work should therefore be self-explanatory.  
   304   examples with the resulting goal state. How
       
   305   they work should be self-explanatory.  
   302 *}
   306 *}
   303 
   307 
   304 lemma shows "P \<and> Q"
   308 lemma shows "P \<and> Q"
   305 apply(tactic {* rtac @{thm conjI} 1 *})
   309 apply(tactic {* rtac @{thm conjI} 1 *})
   306 txt{*@{subgoals [display]}*}
   310 txt{*\begin{minipage}{\textwidth}
       
   311      @{subgoals [display]}
       
   312      \end{minipage}*}
   307 (*<*)oops(*>*)
   313 (*<*)oops(*>*)
   308 
   314 
   309 lemma shows "P \<and> Q \<Longrightarrow> False"
   315 lemma shows "P \<and> Q \<Longrightarrow> False"
   310 apply(tactic {* etac @{thm conjE} 1 *})
   316 apply(tactic {* etac @{thm conjE} 1 *})
   311 txt{*@{subgoals [display]}*}
   317 txt{*\begin{minipage}{\textwidth}
       
   318      @{subgoals [display]}
       
   319      \end{minipage}*}
   312 (*<*)oops(*>*)
   320 (*<*)oops(*>*)
   313 
   321 
   314 lemma shows "False \<and> True \<Longrightarrow> False"
   322 lemma shows "False \<and> True \<Longrightarrow> False"
   315 apply(tactic {* dtac @{thm conjunct2} 1 *})
   323 apply(tactic {* dtac @{thm conjunct2} 1 *})
   316 txt{*@{subgoals [display]}*}
   324 txt{*\begin{minipage}{\textwidth}
       
   325      @{subgoals [display]}
       
   326      \end{minipage}*}
   317 (*<*)oops(*>*)
   327 (*<*)oops(*>*)
   318 
   328 
   319 text {*
   329 text {*
   320   As mentioned above, most basic tactics take a number as argument, which
   330   As mentioned above, most basic tactics take a number as argument, which
   321   addresses to subgoal they are analysing.
   331   addresses to subgoal they are analysing.
   322 *}
   332 *}
   323 
   333 
   324 lemma shows "Foo" and "P \<and> Q"
   334 lemma shows "Foo" and "P \<and> Q"
   325 apply(tactic {* rtac @{thm conjI} 2 *})
   335 apply(tactic {* rtac @{thm conjI} 2 *})
   326 txt {*@{subgoals [display]}*}
   336 txt {*\begin{minipage}{\textwidth}
       
   337       @{subgoals [display]}
       
   338       \end{minipage}*}
   327 (*<*)oops(*>*)
   339 (*<*)oops(*>*)
   328 
   340 
   329 text {* 
   341 text {* 
   330   Corresponding to @{ML rtac}, there is also the tactic @{ML resolve_tac}, which
   342   Corresponding to @{ML rtac}, there is also the tactic @{ML resolve_tac}, which
   331   however expects a list of theorems as arguments. From this list it will apply with 
   343   however expects a list of theorems as arguments. From this list it will apply with 
   341 *}
   353 *}
   342 
   354 
   343 lemma shows "C \<longrightarrow> (A \<and> B)" and "(A \<longrightarrow> B) \<and> C"
   355 lemma shows "C \<longrightarrow> (A \<and> B)" and "(A \<longrightarrow> B) \<and> C"
   344 apply(tactic {* resolve_tac_xmp 1 *})
   356 apply(tactic {* resolve_tac_xmp 1 *})
   345 apply(tactic {* resolve_tac_xmp 2 *})
   357 apply(tactic {* resolve_tac_xmp 2 *})
   346 txt{* @{subgoals [display]} *}
   358 txt{*\begin{minipage}{\textwidth}
       
   359      @{subgoals [display]} 
       
   360      \end{minipage}*}
   347 (*<*)oops(*>*)
   361 (*<*)oops(*>*)
   348 
   362 
   349 text {* 
   363 text {* 
   350   Similarly versions exists for @{ML atac} (@{ML assume_tac}), @{ML etac} 
   364   Similarly versions exists for @{ML atac} (@{ML assume_tac}), @{ML etac} 
   351   (@{ML eresolve_tac}) and so on.
   365   (@{ML eresolve_tac}) and so on.
   357 lemma shows "False \<Longrightarrow> True"
   371 lemma shows "False \<Longrightarrow> True"
   358 apply(tactic {* print_tac "foo message" *})
   372 apply(tactic {* print_tac "foo message" *})
   359 (*<*)oops(*>*)
   373 (*<*)oops(*>*)
   360 
   374 
   361 text {*
   375 text {*
   362   Also for useful for debugging purposes are the tactics @{ML all_tac} and
   376   
   363   @{ML no_tac}. The former always succeeds (but does not change the goal state), and
       
   364   the latter always fails.
       
   365 
       
   366   (FIXME explain RS MRS)
   377   (FIXME explain RS MRS)
   367 
   378 
   368   Often proofs involve elaborate operations on assumptions and variables
   379   Often proofs involve elaborate operations on assumptions and 
   369   @{text "\<And>"}-quantified in the goal state. To do such operations on the ML-level 
   380   @{text "\<And>"}-quantified variables. To do such operations on the ML-level 
   370   using the basic tactics, is very unwieldy and brittle. Some convenience and
   381   using the basic tactics is very unwieldy and brittle. Some convenience and
   371   safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters 
   382   safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters 
   372   and binds the various components of a proof state into a record. 
   383   and binds the various components of a proof state into a record. 
   373 *}
   384 *}
   374 
   385 
   375 text_raw{*
   386 text_raw{*
   424   \end{quote}
   435   \end{quote}
   425 
   436 
   426   Note in the actual output the brown colour of the variables @{term x} and 
   437   Note in the actual output the brown colour of the variables @{term x} and 
   427   @{term y}. Although parameters in the original goal, they are fixed inside
   438   @{term y}. Although parameters in the original goal, they are fixed inside
   428   the subproof. Similarly the schematic variable @{term z}. The assumption 
   439   the subproof. Similarly the schematic variable @{term z}. The assumption 
   429   is bound once as @{ML_type cterm} to the record-variable @{text asms} and 
   440   @{prop "A x y"} is bound once as @{ML_type cterm} to the record-variable 
   430   another time as @{ML_type thm} to @{text prems}.
   441   @{text asms} and another time as @{ML_type thm} to @{text prems}.
   431 
   442 
   432   Notice also that we had to append @{text "?"} to \isacommand{apply}. The 
   443   Notice also that we had to append @{text "?"} to \isacommand{apply}. The 
   433   reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely.
   444   reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely.
   434   Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof
   445   Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof
   435   obviously fails. The question-mark allows us to recover from this failure
   446   obviously fails. The question-mark allows us to recover from this failure
   436   in a graceful manner so that the warning messages are not overwritten
   447   in a graceful manner so that the warning messages are not overwritten
   437   by the error message.
   448   by an error message.
   438 
   449 
   439   If we continue the proof script by applying the @{text impI}-rule
   450   If we continue the proof script by applying the @{text impI}-rule
   440 *}
   451 *}
   441 
   452 
   442 apply(rule impI)
   453 apply(rule impI)
   456   \end{quote}
   467   \end{quote}
   457 *}
   468 *}
   458 (*<*)oops(*>*)
   469 (*<*)oops(*>*)
   459 
   470 
   460 text {*
   471 text {*
   461   where we now also have @{term "B y x"} as assumption.
   472   where we now also have @{term "B y x"} as an assumption.
   462 
   473 
   463   One convenience of @{ML SUBPROOF} is that we can apply assumption
   474   One convenience of @{ML SUBPROOF} is that we can apply assumption
   464   using the usual tactics, because the parameter @{text prems} 
   475   using the usual tactics, because the parameter @{text prems} 
   465   contains the assumptions as theorems. With this we can easily 
   476   contains the assumptions as theorems. With this we can easily 
   466   implement a tactic that almost behaves like @{ML atac}:
   477   implement a tactic that almost behaves like @{ML atac}:
   467 *}
   478 *}
   468 
   479 
       
   480 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*}
   469 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
   481 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
   470 apply(tactic 
   482 apply(tactic {* atac' @{context} 1 *})
   471        {* SUBPROOF (fn {prems, ...} => resolve_tac prems 1) @{context} 1 *})
       
   472 txt{* yields
   483 txt{* yields
   473       @{subgoals [display]} *}
   484       @{subgoals [display]} *}
   474 (*<*)oops(*>*)
   485 (*<*)oops(*>*)
   475 
       
   476 
   486 
   477 text {*
   487 text {*
   478   The restriction in this tactic is that it cannot instantiate any
   488   The restriction in this tactic is that it cannot instantiate any
   479   schematic variables. This might be seen as a defect, but is actually
   489   schematic variables. This might be seen as a defect, but is actually
   480   an advantage in the situations for which @{ML SUBPROOF} was designed: 
   490   an advantage in the situations for which @{ML SUBPROOF} was designed: 
   481   the reason is that instantiation of schematic variables can potentially 
   491   the reason is that instantiation of schematic variables can affect 
   482   has affect several goals and can render them unprovable.  
   492   several goals and can render them unprovable. @{ML SUBPROOF} is meant 
   483 
   493   to avoid this.
   484   A similar but less powerful function is @{ML SUBGOAL}. It allows you to 
   494 
   485   inspect a subgoal specified by a number. 
   495   Notice that @{ML atac'} calls @{ML resolve_tac} with the subgoal
       
   496   number @{text "1"} and also the ``outer'' call to @{ML SUBPROOF} in 
       
   497   the \isacommand{apply}-step uses @{text "1"}. Another advantage 
       
   498   of @{ML SUBGOAL} is that the addressing  inside it is completely 
       
   499   local to the proof inside. It is therefore possible to also apply 
       
   500   @{ML atac'} to the second goal:
       
   501 *}
       
   502 
       
   503 lemma shows "True" and "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
       
   504 apply(tactic {* atac' @{context} 2 *})
       
   505 txt{* This gives:
       
   506       @{subgoals [display]} *}
       
   507 (*<*)oops(*>*)
       
   508 
       
   509 
       
   510 text {*
       
   511   A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. 
       
   512   It allows you to inspect a subgoal specified by a number. With this we can 
       
   513   implement a little tactic that applies a rule corresponding to its 
       
   514   topmost connective. The tactic should only apply ``safe'' rules (that is
       
   515   which do not render the goal unprovable). For this we can write:
   486 *}
   516 *}
   487 
   517 
   488 ML %linenumbers{*fun select_tac (t,i) =
   518 ML %linenumbers{*fun select_tac (t,i) =
   489   case t of
   519   case t of
   490      @{term "Trueprop"} $ t' => select_tac (t',i)
   520      @{term "Trueprop"} $ t' => select_tac (t',i)
   491    | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i
   521    | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i
   492    | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i
   522    | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i
   493    | @{term "Not"} $ _ => rtac @{thm notI} i
   523    | @{term "Not"} $ _ => rtac @{thm notI} i
   494    | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i
   524    | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i
   495    | _ => no_tac*}
   525    | _ => all_tac*}
   496 
   526 
   497 lemma shows "A \<and> B" "A \<longrightarrow> B" "\<forall>x. C x"
   527 lemma shows "A \<and> B" "A \<longrightarrow> B" "\<forall>x. C x" "D \<Longrightarrow> E"
       
   528 apply(tactic {* SUBGOAL select_tac 4 *})
       
   529 apply(tactic {* SUBGOAL select_tac 3 *})
       
   530 apply(tactic {* SUBGOAL select_tac 2 *})
   498 apply(tactic {* SUBGOAL select_tac 1 *})
   531 apply(tactic {* SUBGOAL select_tac 1 *})
   499 apply(tactic {* SUBGOAL select_tac 3 *})
       
   500 apply(tactic {* SUBGOAL select_tac 4 *})
       
   501 txt{* @{subgoals [display]} *}
   532 txt{* @{subgoals [display]} *}
   502 (*<*)oops(*>*)
   533 (*<*)oops(*>*)
   503 
   534 
   504 text {*
   535 text {*
   505   However, this example is contrived, as there are much simpler ways
   536   However, this example is contrived, as there are much simpler ways
   506   to implement a proof procedure like the one above. They will be explained
   537   to implement a proof procedure like the one above. They will be explained
   507   in the next section.
   538   in the next section.
       
   539 
       
   540   (Notice that we applied the goals in reverse order)
   508 
   541 
   509   A variant of @{ML SUBGOAL} is @{ML CSUBGOAL} which allows access to the goal
   542   A variant of @{ML SUBGOAL} is @{ML CSUBGOAL} which allows access to the goal
   510   as @{ML_type cterm} instead of a @{ML_type term}.
   543   as @{ML_type cterm} instead of a @{ML_type term}.
   511 *}
   544 *}
   512 
   545