CookBook/Tactical.thy
changeset 105 f49dc7e96235
parent 104 5dcad9348e4d
child 107 258ce361ba1b
equal deleted inserted replaced
104:5dcad9348e4d 105:f49dc7e96235
     3 begin
     3 begin
     4 
     4 
     5 chapter {* Tactical Reasoning\label{chp:tactical} *}
     5 chapter {* Tactical Reasoning\label{chp:tactical} *}
     6 
     6 
     7 text {*
     7 text {*
     8 
     8   The main reason for descending to the ML-level of Isabelle is to be able to
     9   The main reason for descending to the ML-level of Isabelle is to be
     9   implement automatic proof procedures. Such proof procedures usually lessen
    10   able to implement automatic proof procedures. Such proof procedures usually
    10   considerably the burden of manual reasoning, for example, when introducing
    11   lessen considerably the burden of manual reasoning, for example, when
    11   new definitions. These proof procedures are centred around refining a goal
    12   introducing new definitions. These proof procedures are centred around
    12   state using tactics. This is similar to the \isacommand{apply}-style
    13   refining a goal state using tactics. This is similar to the @{text
    13   reasoning at the user level, where goals are modified in a sequence of proof
    14   apply}-style reasoning at the user level, where goals are modified in a
    14   steps until all of them are solved. However, there are also more structured
    15   sequence of proof steps until all of them are solved. However, there are
    15   operations available on the ML-level that help with the handling of
    16   also more structured operations available on the ML-level that help with 
    16   variables and assumptions.
    17   the handling of variables and assumptions.
       
    18 
    17 
    19 *}
    18 *}
    20 
    19 
    21 section {* Basics of Reasoning with Tactics*}
    20 section {* Basics of Reasoning with Tactics*}
    22 
    21 
    57   @{text xs} that will be generalised once the goal is proved (in our case
    56   @{text xs} that will be generalised once the goal is proved (in our case
    58   @{text P} and @{text Q}). The @{text "tac"} is the tactic that proves the goal;
    57   @{text P} and @{text Q}). The @{text "tac"} is the tactic that proves the goal;
    59   it can make use of the local assumptions (there are none in this example). 
    58   it can make use of the local assumptions (there are none in this example). 
    60   The functions @{ML etac}, @{ML rtac} and @{ML atac} correspond to 
    59   The functions @{ML etac}, @{ML rtac} and @{ML atac} correspond to 
    61   @{text erule}, @{text rule} and @{text assumption}, respectively. 
    60   @{text erule}, @{text rule} and @{text assumption}, respectively. 
    62   The operator @{ML THEN} strings the tactics together. A difference
    61   The operator @{ML THEN} strings the tactics together. 
    63   between the \isacommand{apply}-script and the ML-code is that the
       
    64   former causes the lemma to be stored under the name @{text "disj_swap"}, 
       
    65   whereas the latter does not include any code for this.
       
    66 
    62 
    67   \begin{readmore}
    63   \begin{readmore}
    68   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}
    69   and the file @{ML_file "Pure/goal.ML"}. For more information about the
    65   and the file @{ML_file "Pure/goal.ML"}. For more information about the
    70   internals of goals see \isccite{sec:tactical-goals}.  See @{ML_file
    66   internals of goals see \isccite{sec:tactical-goals}.  See @{ML_file
    71   "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic
    67   "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic
    72   tactics and tactic combinators; see also Chapters 3 and 4 in the old
    68   tactics and tactic combinators; see also Chapters 3 and 4 in the old
    73   Isabelle Reference Manual.
    69   Isabelle Reference Manual.
    74   \end{readmore}
    70   \end{readmore}
    75 
    71 
    76   Note that we used antiquotations for referencing the theorems. We could also
    72   Note that we used antiquotations for referencing the theorems. Many theorems
    77   just have written @{ML "etac disjE 1"} and so on, but this is considered bad
    73   also have ML-bindings with the same name. Therefore, we could also just have
    78   style. The reason is that the binding for @{ML disjE} can be re-assigned by 
    74   written @{ML "etac disjE 1"}, or in case there are no ML-binding obtained
    79   the user and thus one does not have complete control over which theorem is
    75   the theorem dynamically using the theorem @{ML thm}; for example @{ML "etac
    80   actually applied. This problem is nicely prevented by using antiquotations, 
    76   (thm \"disjE\") 1"}. Both ways however are considered bad style. The reason
    81   because then the theorems are fixed statically at compile-time.
    77   is that the binding for @{ML disjE} can be re-assigned by the user and thus
       
    78   one does not have complete control over which theorem is actually
       
    79   applied. This problem is nicely prevented by using antiquotations, because
       
    80   then the theorems are fixed statically at compile-time.
    82 
    81 
    83   During the development of automatic proof procedures, you will often find it 
    82   During the development of automatic proof procedures, you will often find it 
    84   necessary to test a tactic on examples. This can be conveniently 
    83   necessary to test a tactic on examples. This can be conveniently 
    85   done with the command \isacommand{apply}@{text "(tactic \<verbopen> \<dots> \<verbclose>)"}. 
    84   done with the command \isacommand{apply}@{text "(tactic \<verbopen> \<dots> \<verbclose>)"}. 
    86   Consider the following sequence of tactics
    85   Consider the following sequence of tactics
   105   any other function that returns a tactic.
   104   any other function that returns a tactic.
   106 
   105 
   107   The tactic @{ML foo_tac} is just a sequence of simple tactics stringed
   106   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}
   107   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
   108   has a hard-coded number that stands for the subgoal analysed by the
   110   tactic (@{text "1"} stands for the first, or top-most, subgoal). This is 
   109   tactic (@{text "1"} stands for the first, or top-most, subgoal). This hard-coding
   111   sometimes wanted, but usually not. To avoid the explicit numbering in 
   110   of goals is sometimes wanted, but usually it is not. To avoid the explicit numbering, 
   112   the tactic, you can write
   111   you can write
   113 *}
   112 *}
   114 
   113 
   115 ML{*val foo_tac' = 
   114 ML{*val foo_tac' = 
   116       (etac @{thm disjE} 
   115       (etac @{thm disjE} 
   117        THEN' rtac @{thm disjI2} 
   116        THEN' rtac @{thm disjI2} 
   119        THEN' rtac @{thm disjI1} 
   118        THEN' rtac @{thm disjI1} 
   120        THEN' atac)*}
   119        THEN' atac)*}
   121 
   120 
   122 text {* 
   121 text {* 
   123   and then give the number for the subgoal explicitly when the tactic is
   122   and then give the number for the subgoal explicitly when the tactic is
   124   called. For every operator that combines tactics (@{ML THEN} is only one 
   123   called. So in the next proof you can first discharge the second subgoal, and
   125   such operator), a primed version exists. So in the next proof you 
   124   after that the first.
   126   can first discharge the second subgoal, and after that the first.
       
   127 *}
   125 *}
   128 
   126 
   129 lemma "P1 \<or> Q1 \<Longrightarrow> Q1 \<or> P1"
   127 lemma "P1 \<or> Q1 \<Longrightarrow> Q1 \<or> P1"
   130    and "P2 \<or> Q2 \<Longrightarrow> Q2 \<or> P2"
   128    and "P2 \<or> Q2 \<Longrightarrow> Q2 \<or> P2"
   131 apply(tactic {* foo_tac' 2 *})
   129 apply(tactic {* foo_tac' 2 *})
   132 apply(tactic {* foo_tac' 1 *})
   130 apply(tactic {* foo_tac' 1 *})
   133 done
   131 done
   134 
   132 
   135 text {*
   133 text {*
   136   This kind of addressing is more difficult to achieve when the goal is 
   134   This kind of addressing is more difficult to achieve when the goal is 
   137   hard-coded inside the tactic.
   135   hard-coded inside the tactic. For every operator that combines tactics 
       
   136   (@{ML THEN} is only one such operator) a ``primed'' version exists.
   138 
   137 
   139   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
   140   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
   141   of this form, then @{ML foo_tac} throws the error message:
   140   of this form, then they throw the error message:
   142 
   141 
   143   \begin{isabelle}
   142   \begin{isabelle}
   144   @{text "*** empty result sequence -- proof command failed"}\\
   143   @{text "*** empty result sequence -- proof command failed"}\\
   145   @{text "*** At command \"apply\"."}
   144   @{text "*** At command \"apply\"."}
   146   \end{isabelle}
   145   \end{isabelle}
   147 
   146 
   148   Meaning the tactic failed. The reason for this error message is that tactics 
   147   Meaning the tactics failed. The reason for this error message is that tactics 
   149   are functions that map a goal state to a (lazy) sequence of successor states, 
   148   are functions that map a goal state to a (lazy) sequence of successor states, 
   150   hence the type of a tactic is:
   149   hence the type of a tactic is:
   151   
   150   
   152   @{text [display, gray] "type tactic = thm -> thm Seq.seq"}
   151   @{text [display, gray] "type tactic = thm -> thm Seq.seq"}
   153 
   152 
   154   It is custom that if a tactic fails, it should return the empty sequence: 
   153   It is custom that if a tactic fails, it should return the empty sequence: 
   155   your own tactics should not raise exceptions willy-nilly.
   154   therefore your own tactics should not raise exceptions willy-nilly.
   156 
   155 
   157   The simplest tactics are @{ML no_tac} and @{ML all_tac}. The first returns
   156   The simplest tactics are @{ML no_tac} and @{ML all_tac}. The first returns
   158   the empty sequence and is defined as
   157   the empty sequence and is defined as
   159 *}
   158 *}
   160 
   159 
   169 
   168 
   170 text {*
   169 text {*
   171   which means @{ML all_tac} always succeeds (but also does not make any progress 
   170   which means @{ML all_tac} always succeeds (but also does not make any progress 
   172   with the proof).
   171   with the proof).
   173 
   172 
   174   The lazy list of possible successor states shows through to the user-level 
   173   The lazy list of possible successor states shows through at the user-level 
   175   of Isabelle when using the command \isacommand{back}. For instance in the 
   174   of Isabelle when using the command \isacommand{back}. For instance in the 
   176   following proof, there are two possibilities for how to apply 
   175   following proof, there are two possibilities for how to apply 
   177   @{ML foo_tac'}.
   176   @{ML foo_tac'}.
   178 *}
   177 *}
   179 
   178 
   212  end*}
   211  end*}
   213 
   212 
   214 text {*
   213 text {*
   215   which prints out the given theorem (using the string-function defined 
   214   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
   215   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
   216   now can inspect every proof state in a proof. Consider the proof below: on 
   218   side we show the goal state as shown by the system; on the right-hand
   217   the left-hand side we show the goal state as shown by Isabelle; on the 
   219   side the print out from @{ML my_print_tac}.
   218   right-hand side the print out from @{ML my_print_tac}.
   220 *}
   219 *}
   221 
   220 
   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{* \small 
   226       \begin{tabular}{@ {}l@ {}p{0.7\textwidth}@ {}}
   225       \begin{tabular}{@ {}l@ {}p{0.7\textwidth}@ {}}
   227       \begin{minipage}[t]{0.3\textwidth}
   226       \begin{minipage}[t]{0.3\textwidth}
   273   As can be seen, internally every goal state is an implication of the form
   272   As can be seen, internally every goal state is an implication of the form
   274 
   273 
   275   @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"}
   274   @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"}
   276 
   275 
   277   where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the  
   276   where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the  
   278   subgoals. So in the first step the goal state is always of the form
   277   subgoals. So after setting up the lemma, the goal state is always of the form
   279   @{text "C \<Longrightarrow> (C)"}. Since the goal @{term C} can potentially be an implication, 
   278   @{text "C \<Longrightarrow> (C)"}. Since the goal @{term C} can potentially be an implication, 
   280   there is a ``protector'' wrapped around it (in from of an outermost constant 
   279   there is a ``protector'' wrapped around it (in from of an outermost constant 
   281   @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal;
   280   @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal;
   282   however this constant is invisible in the print out above). This 
   281   however this constant is invisible in the print out above). This 
   283   prevents that premises are misinterpreted as open subgoals. 
   282   prevents that premises of @{text C} are misinterpreted as open subgoals. 
   284   While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they 
   283   While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they 
   285   are expected to leave the conclusion @{term C} intact, with the 
   284   are expected to leave the conclusion @{term C} intact, with the 
   286   exception of possibly instantiating schematic variables. 
   285   exception of possibly instantiating schematic variables. 
   287  
   286  
   288 *}
   287 *}
   289 
   288 
   290 section {* Simple Tactics *}
   289 section {* Simple Tactics *}
   291 
   290 
   292 text {*
   291 text {*
   293   As seen above, the function @{ML atac} corresponds to the assumption tactic.
   292   A simple tactic is @{ML print_tac}, which is useful for low-level debugging of tactics.
       
   293   It just prints out a message and the current goal state.
       
   294 *}
       
   295  
       
   296 lemma shows "False \<Longrightarrow> True"
       
   297 apply(tactic {* print_tac "foo message" *})
       
   298 (*<*)oops(*>*)
       
   299 
       
   300 text {*
       
   301   Another simple tactic is the function @{ML atac}, which, as shown in the previous
       
   302   section, corresponds to the assumption command.
   294 *}
   303 *}
   295 
   304 
   296 lemma shows "P \<Longrightarrow> P"
   305 lemma shows "P \<Longrightarrow> P"
   297 apply(tactic {* atac 1 *})
   306 apply(tactic {* atac 1 *})
   298 done
   307 done
   325      @{subgoals [display]}
   334      @{subgoals [display]}
   326      \end{minipage}*}
   335      \end{minipage}*}
   327 (*<*)oops(*>*)
   336 (*<*)oops(*>*)
   328 
   337 
   329 text {*
   338 text {*
   330   As mentioned above, most basic tactics take a number as argument, which
   339   As mentioned in the previous section, most basic tactics take a number as 
   331   addresses to subgoal they are analysing.
   340   argument, which addresses the subgoal they are analysing. In the proof below,
       
   341   we first break up the second subgoal by focusing on this subgoal first.
   332 *}
   342 *}
   333 
   343 
   334 lemma shows "Foo" and "P \<and> Q"
   344 lemma shows "Foo" and "P \<and> Q"
   335 apply(tactic {* rtac @{thm conjI} 2 *})
   345 apply(tactic {* rtac @{thm conjI} 2 *})
   336 txt {*\begin{minipage}{\textwidth}
   346 txt {*\begin{minipage}{\textwidth}
   337       @{subgoals [display]}
   347       @{subgoals [display]}
   338       \end{minipage}*}
   348       \end{minipage}*}
   339 (*<*)oops(*>*)
   349 (*<*)oops(*>*)
   340 
   350 
   341 text {* 
   351 text {* 
   342   Corresponding to @{ML rtac}, there is also the tactic @{ML resolve_tac}, which
   352   The function @{ML resolve_tac} is similar to @{ML rtac}, except that it
   343   however expects a list of theorems as arguments. From this list it will apply with 
   353   expects a list of theorems as arguments. From this list it will apply the
   344   the first applicable theorem (later theorems that are also applicable can be
   354   first applicable theorem (later theorems that are also applicable can be
   345   explored via the lazy sequences mechanism). Given the abbreviation
   355   explored via the lazy sequences mechanism). Given the code
   346 *}
   356 *}
   347 
   357 
   348 ML{*val resolve_tac_xmp = resolve_tac [@{thm impI}, @{thm conjI}]*}
   358 ML{*val resolve_tac_xmp = resolve_tac [@{thm impI}, @{thm conjI}]*}
   349 
   359 
   350 text {*
   360 text {*
   360      \end{minipage}*}
   370      \end{minipage}*}
   361 (*<*)oops(*>*)
   371 (*<*)oops(*>*)
   362 
   372 
   363 text {* 
   373 text {* 
   364   Similarly versions exists for @{ML atac} (@{ML assume_tac}), @{ML etac} 
   374   Similarly versions exists for @{ML atac} (@{ML assume_tac}), @{ML etac} 
   365   (@{ML eresolve_tac}) and so on.
   375   (@{ML eresolve_tac}) and so on. 
   366 
   376 
   367   The tactic @{ML print_tac} is useful for low-level debugging of tactics: it
   377   (FIXME: @{ML cut_facts_tac})
   368   prints out a message and the current goal state.
   378 
   369 *}
   379   Since rules are applied using higher-order unification, an automatic proof
   370  
   380   procedure might become too fragile, if it just applies inference rules shown
   371 lemma shows "False \<Longrightarrow> True"
   381   in the fashion above.  More constraints can be introduced by
   372 apply(tactic {* print_tac "foo message" *})
   382   pre-instantiating theorems with other theorems. You can do this using the
   373 (*<*)oops(*>*)
   383   function @{ML RS}. For example
   374 
       
   375 text {*
       
   376   
   384   
   377   (FIXME explain RS MRS)
   385   @{ML_response_fake [display,gray]
       
   386   "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"}
       
   387 
       
   388   instantiates the first premise of the @{text conjI}-rule with the
       
   389   rule @{text disjI1}. The function @{ML RSN} is similar, but 
       
   390   takes a number and makes explicit which premise should be instantiated. 
       
   391   To improve readability we are going use the following function
       
   392 *}
       
   393 
       
   394 ML{*fun no_vars ctxt thm =
       
   395 let 
       
   396   val ((_, [thm']), _) = Variable.import_thms true [thm] ctxt
       
   397 in
       
   398   thm'
       
   399 end*}
       
   400 
       
   401 text {*
       
   402   to transform the schematic variables of a theorem into free variables. 
       
   403   This means for the @{ML RS}-expression above:
       
   404 
       
   405   @{ML_response_fake [display,gray]
       
   406   "no_vars @{context} (@{thm disjI1} RS @{thm conjI})" "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> Q"}
       
   407 
       
   408   If you want to instantiate more than one premise, you can use the function 
       
   409   @{ML MRS}:
       
   410 
       
   411   @{ML_response_fake [display,gray]
       
   412   "no_vars @{context} ([@{thm disjI1}, @{thm disjI2}] MRS @{thm conjI})" 
       
   413   "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> (Pa \<or> Q)"}
       
   414 
       
   415   If you need to instantiate lists of theorems, you can use the
       
   416   functions @{ML RL} and @{ML MRL}. For example below every
       
   417   theorem in the first list is instantiated against every theorem
       
   418   in the second.
       
   419 
       
   420   @{ML_response_fake [display,gray]
       
   421    "[@{thm impI}, @{thm disjI2}] RL [@{thm conjI}, @{thm disjI1}]" 
       
   422 "[\<lbrakk>P \<Longrightarrow> Q; Qa\<rbrakk> \<Longrightarrow> (P \<longrightarrow> Q) \<and> Qa,
       
   423  \<lbrakk>Q; Qa\<rbrakk> \<Longrightarrow> (P \<or> Q) \<and> Qa,
       
   424  (P \<Longrightarrow> Q) \<Longrightarrow> (P \<longrightarrow> Q) \<or> Qa,
       
   425  Q \<Longrightarrow> (P \<or> Q) \<or> Qa]"}
       
   426 
       
   427   \begin{readmore}
       
   428   The combinators for instantiating theorems are defined in @{ML_file "Pure/drule.ML"}.
       
   429   \end{readmore}
   378 
   430 
   379   Often proofs involve elaborate operations on assumptions and 
   431   Often proofs involve elaborate operations on assumptions and 
   380   @{text "\<And>"}-quantified variables. To do such operations on the ML-level 
   432   @{text "\<And>"}-quantified variables. To do such operations on the ML-level 
   381   using the basic tactics is very unwieldy and brittle. Some convenience and
   433   using the basic tactics is very unwieldy and brittle. Some convenience and
   382   safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters 
   434   safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters 
   383   and binds the various components of a proof state into a record. 
   435   and binds the various components of a proof state into a record. 
       
   436   To see what happens, assume the function defined in Figure~\ref{fig:sptac}, which
       
   437   takes a record as argument and just prints out the content of this record (using the 
       
   438   string transformation functions defined in Section~\ref{sec:printing}). Consider
       
   439   now the proof
   384 *}
   440 *}
   385 
   441 
   386 text_raw{*
   442 text_raw{*
   387 \begin{figure}
   443 \begin{figure}
   388 \begin{isabelle}
   444 \begin{isabelle}
   404     no_tac 
   460     no_tac 
   405   end*}
   461   end*}
   406 text_raw{*
   462 text_raw{*
   407 \end{isabelle}
   463 \end{isabelle}
   408 \caption{A function that prints out the various parameters provided by the tactic
   464 \caption{A function that prints out the various parameters provided by the tactic
   409  @{ML SUBPROOF}. It uses the functions extracting strings from @{ML_type cterm}s 
   465  @{ML SUBPROOF}. It uses the functions defined in Section~\ref{sec:printing} for
   410   and @{ML_type thm}s, which are defined in Section~\ref{sec:printing}.\label{fig:sptac}}
   466   extracting strings from @{ML_type cterm}s and @{ML_type thm}s.\label{fig:sptac}}
   411 \end{figure}
   467 \end{figure}
   412 *}
   468 *}
   413 
   469 
   414 text {*
       
   415   To see what happens, assume the function defined in Figure~\ref{fig:sptac}, which
       
   416   takes a record as argument and just prints out the content of this record (using the 
       
   417   string transformation functions defined in Section~\ref{sec:printing}). Consider
       
   418   now the proof
       
   419 *}
       
   420 
   470 
   421 lemma shows "\<And>x y. A x y \<Longrightarrow> B y x \<longrightarrow> C (?z y) x"
   471 lemma shows "\<And>x y. A x y \<Longrightarrow> B y x \<longrightarrow> C (?z y) x"
   422 apply(tactic {* SUBPROOF sp_tac @{context} 1 *})?
   472 apply(tactic {* SUBPROOF sp_tac @{context} 1 *})?
   423 
   473 
   424 txt {*
   474 txt {*
   433   premises:    & @{term "A x y"}
   483   premises:    & @{term "A x y"}
   434   \end{tabular}
   484   \end{tabular}
   435   \end{quote}
   485   \end{quote}
   436 
   486 
   437   Note in the actual output the brown colour of the variables @{term x} and 
   487   Note in the actual output the brown colour of the variables @{term x} and 
   438   @{term y}. Although parameters in the original goal, they are fixed inside
   488   @{term y}. Although they are parameters in the original goal, they are fixed inside
   439   the subproof. Similarly the schematic variable @{term z}. The assumption 
   489   the subproof. Similarly the schematic variable @{term z}. The assumption 
   440   @{prop "A x y"} is bound once as @{ML_type cterm} to the record-variable 
   490   @{prop "A x y"} is bound as @{ML_type cterm} to the record-variable 
   441   @{text asms} and another time as @{ML_type thm} to @{text prems}.
   491   @{text asms} but also as @{ML_type thm} to @{text prems}.
   442 
   492 
   443   Notice also that we had to append @{text "?"} to \isacommand{apply}. The 
   493   Notice also that we had to append @{text "?"} to \isacommand{apply}. The 
   444   reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely.
   494   reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely.
   445   Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof
   495   Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof
   446   obviously fails. The question-mark allows us to recover from this failure
   496   obviously fails. The question-mark allows us to recover from this failure
   469 (*<*)oops(*>*)
   519 (*<*)oops(*>*)
   470 
   520 
   471 text {*
   521 text {*
   472   where we now also have @{term "B y x"} as an assumption.
   522   where we now also have @{term "B y x"} as an assumption.
   473 
   523 
   474   One convenience of @{ML SUBPROOF} is that we can apply assumption
   524   One convenience of @{ML SUBPROOF} is that we can apply the assumptions
   475   using the usual tactics, because the parameter @{text prems} 
   525   using the usual tactics, because the parameter @{text prems} 
   476   contains the assumptions as theorems. With this we can easily 
   526   contains them as theorems. With this we can easily 
   477   implement a tactic that almost behaves like @{ML atac}:
   527   implement a tactic that almost behaves like @{ML atac}, namely:
   478 *}
   528 *}
   479 
   529 
   480 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*}
   530 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*}
   481 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
   531 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
   482 apply(tactic {* atac' @{context} 1 *})
   532 apply(tactic {* atac' @{context} 1 *})
   494 
   544 
   495   Notice that @{ML atac'} calls @{ML resolve_tac} with the subgoal
   545   Notice that @{ML atac'} calls @{ML resolve_tac} with the subgoal
   496   number @{text "1"} and also the ``outer'' call to @{ML SUBPROOF} in 
   546   number @{text "1"} and also the ``outer'' call to @{ML SUBPROOF} in 
   497   the \isacommand{apply}-step uses @{text "1"}. Another advantage 
   547   the \isacommand{apply}-step uses @{text "1"}. Another advantage 
   498   of @{ML SUBGOAL} is that the addressing  inside it is completely 
   548   of @{ML SUBGOAL} is that the addressing  inside it is completely 
   499   local to the proof inside. It is therefore possible to also apply 
   549   local to the subproof inside. It is therefore possible to also apply 
   500   @{ML atac'} to the second goal:
   550   @{ML atac'} to the second goal:
   501 *}
   551 *}
   502 
   552 
   503 lemma shows "True" and "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y"
   553 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 *})
   554 apply(tactic {* atac' @{context} 2 *})
   505 txt{* This gives:
   555 apply(rule TrueI)
   506       @{subgoals [display]} *}
   556 done
   507 (*<*)oops(*>*)
   557 
   508 
   558 
   509 
   559 text {*
   510 text {*
   560   \begin{readmore}
       
   561   The function @{ML SUBPROOF} is defined in @{ML_file "Pure/subgoal.ML"} and
       
   562   also described in \isccite{sec:results}. 
       
   563   \end{readmore}
       
   564 
   511   A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. 
   565   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 
   566   It allows you to inspect a specified subgoal. With this you can implement 
   513   implement a little tactic that applies a rule corresponding to its 
   567   a tactic that applies a rule according to its topmost connective (we only 
   514   topmost connective. The tactic should only apply ``safe'' rules (that is
   568   analyse a few connectives). The tactic is as follows:
   515   which do not render the goal unprovable). For this we can write:
       
   516 *}
   569 *}
   517 
   570 
   518 ML %linenumbers{*fun select_tac (t,i) =
   571 ML %linenumbers{*fun select_tac (t,i) =
   519   case t of
   572   case t of
   520      @{term "Trueprop"} $ t' => select_tac (t',i)
   573      @{term "Trueprop"} $ t' => select_tac (t',i)
   522    | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i
   575    | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i
   523    | @{term "Not"} $ _ => rtac @{thm notI} i
   576    | @{term "Not"} $ _ => rtac @{thm notI} i
   524    | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i
   577    | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i
   525    | _ => all_tac*}
   578    | _ => all_tac*}
   526 
   579 
   527 lemma shows "A \<and> B" "A \<longrightarrow> B" "\<forall>x. C x" "D \<Longrightarrow> E"
   580 text {*
       
   581   In line 3 you need to decend under the outermost @{term "Trueprop"} in order
       
   582   to get to the connective you like to analyse. Otherwise goals @{prop "A \<and> B"} 
       
   583   are not bropek up. In line 7, the pattern cannot be constructed using the
       
   584   @{text "@term"}-antiquotation, because that would fix the type of the 
       
   585   quantified variable. In this case you really have to construct the pattern
       
   586   by using the term-constructors. The other cases work, because their type
       
   587   is always bool. In case that the goal does not fall into any of the categorories, 
       
   588   then we chose to just return @{ML all_tac} (i.e., the tactic never fails). 
       
   589 
       
   590   Let us now see how to apply this tactic.
       
   591 *}
       
   592 
       
   593 
       
   594 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F"
   528 apply(tactic {* SUBGOAL select_tac 4 *})
   595 apply(tactic {* SUBGOAL select_tac 4 *})
   529 apply(tactic {* SUBGOAL select_tac 3 *})
   596 apply(tactic {* SUBGOAL select_tac 3 *})
   530 apply(tactic {* SUBGOAL select_tac 2 *})
   597 apply(tactic {* SUBGOAL select_tac 2 *})
   531 apply(tactic {* SUBGOAL select_tac 1 *})
   598 apply(tactic {* SUBGOAL select_tac 1 *})
   532 txt{* @{subgoals [display]} *}
   599 txt{* @{subgoals [display]} *}
   533 (*<*)oops(*>*)
   600 (*<*)oops(*>*)
   534 
   601 
   535 text {*
   602 text {*
   536   However, this example is contrived, as there are much simpler ways
   603   Note that we applied it in ``reverse'' order. This is a trick in 
   537   to implement a proof procedure like the one above. They will be explained
   604   order to be independent from what subgoals the rule produced. If we had
   538   in the next section.
   605   it applied in the other order 
   539 
   606 *}
   540   (Notice that we applied the goals in reverse order)
   607 
   541 
   608 lemma shows "A \<and> B" and "A \<longrightarrow> B \<longrightarrow>C" and "\<forall>x. D x" and "E \<Longrightarrow> F"
   542   A variant of @{ML SUBGOAL} is @{ML CSUBGOAL} which allows access to the goal
   609 apply(tactic {* SUBGOAL select_tac 1 *})
   543   as @{ML_type cterm} instead of a @{ML_type term}.
   610 apply(tactic {* SUBGOAL select_tac 3 *})
   544 *}
   611 apply(tactic {* SUBGOAL select_tac 4 *})
   545 
   612 apply(tactic {* SUBGOAL select_tac 5 *})
   546 
   613 (*<*)oops(*>*)
   547 section {* Operations on Tactics *}
   614 
   548 
   615 text {*
   549 text {* @{ML THEN} *}
   616   then we have to be careful to not apply the tactic to the two subgoals the
       
   617   first goal produced. This can be messy in an automated proof script. The
       
   618   reverse application, on the other hand, is easy to implement.
       
   619 
       
   620   However, this example is contrived: there are much simpler ways to implement
       
   621   such proof procedure that analyses a goal according to its topmost
       
   622   connective. They will be explained in the next section.
       
   623 *}
       
   624 
       
   625 section {* Tactic Combinators *}
       
   626 
       
   627 text {* 
       
   628   To be able to implement powerful tactics out of smaller component tactics, 
       
   629   Isabelle provides tactic combinators. In the previous section we already
       
   630   used @{ML THEN} which strings two tactics together in sequence. For example:
       
   631 *}
   550 
   632 
   551 lemma shows "(Foo \<and> Bar) \<and> False"
   633 lemma shows "(Foo \<and> Bar) \<and> False"
   552 apply(tactic {* (rtac @{thm conjI} 1) 
   634 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *})
   553                  THEN (rtac @{thm conjI} 1) *})
   635 txt {* \begin{minipage}{\textwidth}
   554 txt {* @{subgoals [display]} *}
   636        @{subgoals [display]} 
   555 (*<*)oops(*>*)
   637        \end{minipage} *}
       
   638 (*<*)oops(*>*)
       
   639 
       
   640 text {*
       
   641   If you want to avoid the hard-coded subgoal addressing, then you can use
       
   642   @{ML THEN'}. For example:
       
   643 *}
       
   644 
       
   645 lemma shows "(Foo \<and> Bar) \<and> False"
       
   646 apply(tactic {* (rtac @{thm conjI} THEN' rtac @{thm conjI}) 1 *})
       
   647 txt {* \begin{minipage}{\textwidth}
       
   648        @{subgoals [display]} 
       
   649        \end{minipage} *}
       
   650 (*<*)oops(*>*)
       
   651 
       
   652 text {* 
       
   653   For most tactic combinators such a ``primed'' version exists.
       
   654   In what follows we will, whenever appropriate, prefer the primed version of
       
   655   the tactic combinator and omit to mention the simple one. 
       
   656 
       
   657   With @{ML THEN} and @{ML THEN'} it must be guaranteed that both tactics 
       
   658   sucessfully apply; otherwise the whole tactic will fail. If you want to
       
   659   try out either one tactic, then you can use @{ML ORELSE'}. For 
       
   660   example
       
   661 *}
   556 
   662 
   557 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*}
   663 ML{*val orelse_xmp = (rtac @{thm disjI1} ORELSE' rtac @{thm conjI})*}
       
   664 
       
   665 text {*
       
   666   will first try out rule @{text disjI} and after that @{text conjI}.
       
   667 *}
   558 
   668 
   559 lemma shows "True \<and> False" and "Foo \<or> Bar"
   669 lemma shows "True \<and> False" and "Foo \<or> Bar"
   560 apply(tactic {* orelse_xmp 1 *})
   670 apply(tactic {* orelse_xmp 1 *})
   561 apply(tactic {* orelse_xmp 3 *})
   671 apply(tactic {* orelse_xmp 3 *})
   562 txt {* @{subgoals [display]} *}
   672 txt {* @{subgoals [display]} *}
   563 (*<*)oops(*>*)
   673 (*<*)oops(*>*)
   564 
   674 
   565 
   675 
   566 text {*
   676 text {*
   567   @{ML EVERY} @{ML REPEAT} @{ML DETERM}
   677   applies 
   568 
   678 
       
   679 
       
   680   @{ML REPEAT} @{ML DETERM}
       
   681 
       
   682 *}
       
   683 
       
   684 section {* Rewriting and Simplifier Tactics *}
       
   685 
       
   686 text {*
   569   @{ML rewrite_goals_tac}
   687   @{ML rewrite_goals_tac}
   570   @{ML cut_facts_tac}
       
   571   @{ML ObjectLogic.full_atomize_tac}
   688   @{ML ObjectLogic.full_atomize_tac}
   572   @{ML ObjectLogic.rulify_tac}
   689   @{ML ObjectLogic.rulify_tac}
   573   @{ML resolve_tac}
   690 *}
   574 *}
   691 
   575 
   692 
   576 section {* Structured Proofs *}
   693 section {* Structured Proofs *}
   577 
   694 
   578 lemma True
   695 lemma True
   579 proof
   696 proof