ProgTutorial/Package/Ind_Code.thy
changeset 565 cecd7a941885
parent 562 daf404920ab9
child 567 f7c97e64cc2a
equal deleted inserted replaced
564:6e2479089226 565:cecd7a941885
     1 theory Ind_Code
     1 theory Ind_Code
     2 imports Ind_General_Scheme "../First_Steps" 
     2 imports Ind_General_Scheme "../First_Steps" 
     3 begin
     3 begin
     4 
     4 
     5 section {* The Gory Details\label{sec:code} *} 
     5 section \<open>The Gory Details\label{sec:code}\<close> 
     6 
     6 
     7 text {*
     7 text \<open>
     8   As mentioned before the code falls roughly into three parts: the code that deals
     8   As mentioned before the code falls roughly into three parts: the code that deals
     9   with the definitions, with the induction principles and with the introduction
     9   with the definitions, with the induction principles and with the introduction
    10   rules. In addition there are some administrative functions that string everything 
    10   rules. In addition there are some administrative functions that string everything 
    11   together.
    11   together.
    12 *}
    12 \<close>
    13 
    13 
    14 subsection {* Definitions *}
    14 subsection \<open>Definitions\<close>
    15 
    15 
    16 text {*
    16 text \<open>
    17   We first have to produce for each predicate the user specifies an appropriate
    17   We first have to produce for each predicate the user specifies an appropriate
    18   definition, whose general form is
    18   definition, whose general form is
    19 
    19 
    20   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    20   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    21 
    21 
    22   and then ``register'' the definition inside a local theory. 
    22   and then ``register'' the definition inside a local theory. 
    23   To do the latter, we use the following wrapper for the function
    23   To do the latter, we use the following wrapper for the function
    24   @{ML_ind define in Local_Theory}. The wrapper takes a predicate name, a syntax
    24   @{ML_ind define in Local_Theory}. The wrapper takes a predicate name, a syntax
    25   annotation and a term representing the right-hand side of the definition.
    25   annotation and a term representing the right-hand side of the definition.
    26 *}
    26 \<close>
    27 
    27 
    28 ML %linenosgray{*fun make_defn ((predname, mx), trm) lthy =
    28 ML %linenosgray\<open>fun make_defn ((predname, mx), trm) lthy =
    29 let 
    29 let 
    30   val arg = ((predname, mx), (Binding.empty_atts, trm))
    30   val arg = ((predname, mx), (Binding.empty_atts, trm))
    31   val ((_, (_ , thm)), lthy') = Local_Theory.define arg lthy
    31   val ((_, (_ , thm)), lthy') = Local_Theory.define arg lthy
    32 in 
    32 in 
    33   (thm, lthy') 
    33   (thm, lthy') 
    34 end*}
    34 end\<close>
    35 
    35 
    36 text {*
    36 text \<open>
    37   It returns the definition (as a theorem) and the local theory in which the
    37   It returns the definition (as a theorem) and the local theory in which the
    38   definition has been made. We use @{ML_ind empty_atts in Binding} in Line 3, 
    38   definition has been made. We use @{ML_ind empty_atts in Binding} in Line 3, 
    39   since the definitions for our inductive predicates are not meant to be seen 
    39   since the definitions for our inductive predicates are not meant to be seen 
    40   by the user and therefore do not need to have any theorem attributes. 
    40   by the user and therefore do not need to have any theorem attributes. 
    41  
    41  
    42   The next two functions construct the right-hand sides of the definitions, 
    42   The next two functions construct the right-hand sides of the definitions, 
    43   which are terms whose general form is:
    43   which are terms whose general form is:
    44 
    44 
    45   @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    45   @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    46 
    46 
    47   When constructing these terms, the variables @{text "zs"} need to be chosen so 
    47   When constructing these terms, the variables \<open>zs\<close> need to be chosen so 
    48   that they do not occur in the @{text orules} and also be distinct from the 
    48   that they do not occur in the \<open>orules\<close> and also be distinct from the 
    49   @{text "preds"}.
    49   \<open>preds\<close>.
    50 
    50 
    51 
    51 
    52   The first function, named @{text defn_aux}, constructs the term for one
    52   The first function, named \<open>defn_aux\<close>, constructs the term for one
    53   particular predicate (the argument @{text "pred"} in the code below). The
    53   particular predicate (the argument \<open>pred\<close> in the code below). The
    54   number of arguments of this predicate is determined by the number of
    54   number of arguments of this predicate is determined by the number of
    55   argument types given in @{text "arg_tys"}. The other arguments of the
    55   argument types given in \<open>arg_tys\<close>. The other arguments of the
    56   function are the @{text orules} and all the @{text "preds"}.
    56   function are the \<open>orules\<close> and all the \<open>preds\<close>.
    57 *}
    57 \<close>
    58 
    58 
    59 ML %linenosgray{*fun defn_aux lthy orules preds (pred, arg_tys) =
    59 ML %linenosgray\<open>fun defn_aux lthy orules preds (pred, arg_tys) =
    60 let 
    60 let 
    61   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
    61   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
    62 
    62 
    63   val fresh_args = 
    63   val fresh_args = 
    64         arg_tys 
    64         arg_tys 
    68 in
    68 in
    69   list_comb (pred, fresh_args)
    69   list_comb (pred, fresh_args)
    70   |> fold_rev (curry HOLogic.mk_imp) orules
    70   |> fold_rev (curry HOLogic.mk_imp) orules
    71   |> fold_rev mk_all preds
    71   |> fold_rev mk_all preds
    72   |> fold_rev lambda fresh_args 
    72   |> fold_rev lambda fresh_args 
    73 end*}
    73 end\<close>
    74 
    74 
    75 text {*
    75 text \<open>
    76   The function @{text mk_all} in Line 3 is just a helper function for constructing 
    76   The function \<open>mk_all\<close> in Line 3 is just a helper function for constructing 
    77   universal quantifications. The code in Lines 5 to 9 produces the fresh @{text
    77   universal quantifications. The code in Lines 5 to 9 produces the fresh \<open>zs\<close>. For this it pairs every argument type with the string
    78   "zs"}. For this it pairs every argument type with the string
       
    79   @{text [quotes] "z"} (Line 7); then generates variants for all these strings
    78   @{text [quotes] "z"} (Line 7); then generates variants for all these strings
    80   so that they are unique w.r.t.~to the predicates and @{text "orules"} (Line 8);
    79   so that they are unique w.r.t.~to the predicates and \<open>orules\<close> (Line 8);
    81   in Line 9 it generates the corresponding variable terms for the unique
    80   in Line 9 it generates the corresponding variable terms for the unique
    82   strings.
    81   strings.
    83 
    82 
    84   The unique variables are applied to the predicate in Line 11 using the
    83   The unique variables are applied to the predicate in Line 11 using the
    85   function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in
    84   function @{ML list_comb}; then the \<open>orules\<close> are prefixed (Line 12); in
    86   Line 13 we quantify over all predicates; and in line 14 we just abstract
    85   Line 13 we quantify over all predicates; and in line 14 we just abstract
    87   over all the @{text "zs"}, i.e., the fresh arguments of the
    86   over all the \<open>zs\<close>, i.e., the fresh arguments of the
    88   predicate. A testcase for this function is
    87   predicate. A testcase for this function is
    89 *}
    88 \<close>
    90 
    89 
    91 local_setup %gray {* fn lthy =>
    90 local_setup %gray \<open>fn lthy =>
    92 let
    91 let
    93   val def = defn_aux lthy eo_orules eo_preds (e_pred, e_arg_tys)
    92   val def = defn_aux lthy eo_orules eo_preds (e_pred, e_arg_tys)
    94 in
    93 in
    95   pwriteln (pretty_term lthy def); lthy
    94   pwriteln (pretty_term lthy def); lthy
    96 end *}
    95 end\<close>
    97 
    96 
    98 text {*
    97 text \<open>
    99   where we use the shorthands defined in Figure~\ref{fig:shorthands}.
    98   where we use the shorthands defined in Figure~\ref{fig:shorthands}.
   100   The testcase calls @{ML defn_aux} for the predicate @{text "even"} and prints
    99   The testcase calls @{ML defn_aux} for the predicate \<open>even\<close> and prints
   101   out the generated definition. So we obtain as printout 
   100   out the generated definition. So we obtain as printout 
   102 
   101 
   103   @{text [display] 
   102   @{text [display] 
   104 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   103 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   105                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   104                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   106 
   105 
   107   If we try out the function with the rules for freshness
   106   If we try out the function with the rules for freshness
   108 *}
   107 \<close>
   109 
   108 
   110 local_setup %gray {* fn lthy =>
   109 local_setup %gray \<open>fn lthy =>
   111 let
   110 let
   112   val arg = (fresh_pred, fresh_arg_tys)
   111   val arg = (fresh_pred, fresh_arg_tys)
   113   val def = defn_aux lthy fresh_orules [fresh_pred] arg
   112   val def = defn_aux lthy fresh_orules [fresh_pred] arg
   114 in
   113 in
   115   pwriteln (pretty_term lthy def); lthy
   114   pwriteln (pretty_term lthy def); lthy
   116 end *}
   115 end\<close>
   117 
   116 
   118 
   117 
   119 text {*
   118 text \<open>
   120   we obtain
   119   we obtain
   121 
   120 
   122   @{term [display] 
   121   @{term [display] 
   123 "\<lambda>z za. \<forall>fresh. (\<forall>a b. \<not> a = b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   122 "\<lambda>z za. \<forall>fresh. (\<forall>a b. \<not> a = b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   124                (\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   123                (\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   125                 (\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
   124                 (\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
   126                 (\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"}
   125                 (\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"}
   127 
   126 
   128 
   127 
   129   The second function, named @{text defns}, has to iterate the function
   128   The second function, named \<open>defns\<close>, has to iterate the function
   130   @{ML defn_aux} over all predicates. The argument @{text "preds"} is again
   129   @{ML defn_aux} over all predicates. The argument \<open>preds\<close> is again
   131   the list of predicates as @{ML_type term}s; the argument @{text
   130   the list of predicates as @{ML_type term}s; the argument \<open>prednames\<close> is the list of binding names of the predicates; \<open>mxs\<close> 
   132   "prednames"} is the list of binding names of the predicates; @{text mxs} 
       
   133   are the list of syntax, or mixfix, annotations for the predicates; 
   131   are the list of syntax, or mixfix, annotations for the predicates; 
   134   @{text "arg_tyss"} is the list of argument-type-lists.
   132   \<open>arg_tyss\<close> is the list of argument-type-lists.
   135 *}
   133 \<close>
   136 
   134 
   137 ML %linenosgray{*fun defns rules preds prednames mxs arg_typss lthy =
   135 ML %linenosgray\<open>fun defns rules preds prednames mxs arg_typss lthy =
   138 let
   136 let
   139   val orules = map (Object_Logic.atomize_term lthy) rules
   137   val orules = map (Object_Logic.atomize_term lthy) rules
   140   val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) 
   138   val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) 
   141 in
   139 in
   142   fold_map make_defn (prednames ~~ mxs ~~ defs) lthy
   140   fold_map make_defn (prednames ~~ mxs ~~ defs) lthy
   143 end*}
   141 end\<close>
   144 
   142 
   145 text {*
   143 text \<open>
   146   The user will state the introduction rules using meta-implications and
   144   The user will state the introduction rules using meta-implications and
   147   meta-quanti\-fications. In Line 4, we transform these introduction rules
   145   meta-quanti\-fications. In Line 4, we transform these introduction rules
   148   into the object logic (since definitions cannot be stated with
   146   into the object logic (since definitions cannot be stated with
   149   meta-connectives). To do this transformation we have to obtain the theory
   147   meta-connectives). To do this transformation we have to obtain the theory
   150   behind the local theory using the function @{ML_ind theory_of in Proof_Context} 
   148   behind the local theory using the function @{ML_ind theory_of in Proof_Context} 
   152   @{ML_ind  atomize_term in Object_Logic} to make the transformation (Line 4). The call
   150   @{ML_ind  atomize_term in Object_Logic} to make the transformation (Line 4). The call
   153   to @{ML defn_aux} in Line 5 produces all right-hand sides of the
   151   to @{ML defn_aux} in Line 5 produces all right-hand sides of the
   154   definitions. The actual definitions are then made in Line 7.  The result of
   152   definitions. The actual definitions are then made in Line 7.  The result of
   155   the function is a list of theorems and a local theory (the theorems are
   153   the function is a list of theorems and a local theory (the theorems are
   156   registered with the local theory). A testcase for this function is
   154   registered with the local theory). A testcase for this function is
   157 *}
   155 \<close>
   158 
   156 
   159 local_setup %gray {* fn lthy =>
   157 local_setup %gray \<open>fn lthy =>
   160 let
   158 let
   161   val (defs, lthy') = 
   159   val (defs, lthy') = 
   162     defns eo_rules eo_preds eo_prednames eo_mxs eo_arg_tyss lthy
   160     defns eo_rules eo_preds eo_prednames eo_mxs eo_arg_tyss lthy
   163 in
   161 in
   164   pwriteln (pretty_thms_no_vars lthy' defs); lthy
   162   pwriteln (pretty_thms_no_vars lthy' defs); lthy
   165 end *}
   163 end\<close>
   166 
   164 
   167 text {*
   165 text \<open>
   168   where we feed into the function all parameters corresponding to
   166   where we feed into the function all parameters corresponding to
   169   the @{text even}/@{text odd} example. The definitions we obtain
   167   the \<open>even\<close>/\<open>odd\<close> example. The definitions we obtain
   170   are:
   168   are:
   171 
   169 
   172   @{text [display, break]
   170   @{text [display, break]
   173 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))  
   171 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))  
   174                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   172                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   175 odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   173 odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   176                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   174                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   177 
   175 
   178   Note that in the testcase we return the local theory @{text lthy} 
   176   Note that in the testcase we return the local theory \<open>lthy\<close> 
   179   (not the modified @{text lthy'}). As a result the test case has no effect
   177   (not the modified \<open>lthy'\<close>). As a result the test case has no effect
   180   on the ambient theory. The reason is that if we introduce the
   178   on the ambient theory. The reason is that if we introduce the
   181   definition again, we pollute the name space with two versions of 
   179   definition again, we pollute the name space with two versions of 
   182   @{text "even"} and @{text "odd"}. We want to avoid this here.
   180   \<open>even\<close> and \<open>odd\<close>. We want to avoid this here.
   183 
   181 
   184   This completes the code for introducing the definitions. Next we deal with
   182   This completes the code for introducing the definitions. Next we deal with
   185   the induction principles. 
   183   the induction principles. 
   186 *}
   184 \<close>
   187 
   185 
   188 subsection {* Induction Principles *}
   186 subsection \<open>Induction Principles\<close>
   189 
   187 
   190 text {*
   188 text \<open>
   191   Recall that the manual proof for the induction principle 
   189   Recall that the manual proof for the induction principle 
   192   of @{text "even"} was:
   190   of \<open>even\<close> was:
   193 *}
   191 \<close>
   194 
   192 
   195 lemma manual_ind_prin_even: 
   193 lemma manual_ind_prin_even: 
   196 assumes prem: "even z"
   194 assumes prem: "even z"
   197 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   195 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   198 apply(atomize (full))
   196 apply(atomize (full))
   201 apply(drule spec[where x=P])
   199 apply(drule spec[where x=P])
   202 apply(drule spec[where x=Q])
   200 apply(drule spec[where x=Q])
   203 apply(assumption)
   201 apply(assumption)
   204 done
   202 done
   205 
   203 
   206 text {* 
   204 text \<open>
   207   The code for automating such induction principles has to accomplish two tasks: 
   205   The code for automating such induction principles has to accomplish two tasks: 
   208   constructing the induction principles from the given introduction
   206   constructing the induction principles from the given introduction
   209   rules and then automatically generating proofs for them using a tactic. 
   207   rules and then automatically generating proofs for them using a tactic. 
   210   
   208   
   211   The tactic will use the following helper function for instantiating universal 
   209   The tactic will use the following helper function for instantiating universal 
   212   quantifiers. 
   210   quantifiers. 
   213 *}
   211 \<close>
   214 
   212 
   215 ML %grayML{*fun inst_spec ctrm =
   213 ML %grayML\<open>fun inst_spec ctrm =
   216 let
   214 let
   217   val cty = Thm.ctyp_of_cterm ctrm
   215   val cty = Thm.ctyp_of_cterm ctrm
   218 in 
   216 in 
   219   Thm.instantiate' [SOME cty] [NONE, SOME ctrm] @{thm spec} 
   217   Thm.instantiate' [SOME cty] [NONE, SOME ctrm] @{thm spec} 
   220 end*}
   218 end\<close>
   221 
   219 
   222 text {*
   220 text \<open>
   223   This helper function uses the function @{ML_ind instantiate' in Thm}
   221   This helper function uses the function @{ML_ind instantiate' in Thm}
   224   and instantiates the @{text "?x"} in the theorem @{thm spec} with a given
   222   and instantiates the \<open>?x\<close> in the theorem @{thm spec} with a given
   225   @{ML_type cterm}. We call this helper function in the following
   223   @{ML_type cterm}. We call this helper function in the following
   226   tactic.\label{fun:instspectac}.
   224   tactic.\label{fun:instspectac}.
   227 *}
   225 \<close>
   228 
   226 
   229 ML %grayML{*fun inst_spec_tac ctxt ctrms = 
   227 ML %grayML\<open>fun inst_spec_tac ctxt ctrms = 
   230   EVERY' (map (dresolve_tac ctxt o single o inst_spec) ctrms)*}
   228   EVERY' (map (dresolve_tac ctxt o single o inst_spec) ctrms)\<close>
   231 
   229 
   232 text {*
   230 text \<open>
   233   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   231   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   234   proof below to instantiate the three quantifiers in the assumption. 
   232   proof below to instantiate the three quantifiers in the assumption. 
   235 *}
   233 \<close>
   236 
   234 
   237 lemma 
   235 lemma 
   238 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   236 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   239 shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   237 shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   240 apply (tactic {* 
   238 apply (tactic \<open>
   241   inst_spec_tac @{context} [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
   239   inst_spec_tac @{context} [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1\<close>)
   242 txt {* 
   240 txt \<open>
   243   We obtain the goal state
   241   We obtain the goal state
   244 
   242 
   245   \begin{minipage}{\textwidth}
   243   \begin{minipage}{\textwidth}
   246   @{subgoals} 
   244   @{subgoals} 
   247   \end{minipage}*}
   245   \end{minipage}\<close>
   248 (*<*)oops(*>*)
   246 (*<*)oops(*>*)
   249 
   247 
   250 text {*
   248 text \<open>
   251   The complete tactic for proving the induction principles can now
   249   The complete tactic for proving the induction principles can now
   252   be implemented as follows:
   250   be implemented as follows:
   253 *}
   251 \<close>
   254 
   252 
   255 ML %linenosgray{*fun ind_tac ctxt defs prem insts =
   253 ML %linenosgray\<open>fun ind_tac ctxt defs prem insts =
   256   EVERY1 [Object_Logic.full_atomize_tac ctxt,
   254   EVERY1 [Object_Logic.full_atomize_tac ctxt,
   257           cut_facts_tac prem,
   255           cut_facts_tac prem,
   258           rewrite_goal_tac ctxt defs,
   256           rewrite_goal_tac ctxt defs,
   259           inst_spec_tac ctxt insts,
   257           inst_spec_tac ctxt insts,
   260           assume_tac ctxt]*}
   258           assume_tac ctxt]\<close>
   261 
   259 
   262 text {*
   260 text \<open>
   263   We have to give it as arguments the definitions, the premise (a list of
   261   We have to give it as arguments the definitions, the premise (a list of
   264   formulae) and the instantiations. The premise is @{text "even n"} in lemma
   262   formulae) and the instantiations. The premise is \<open>even n\<close> in lemma
   265   @{thm [source] manual_ind_prin_even} shown above; in our code it will always be a list
   263   @{thm [source] manual_ind_prin_even} shown above; in our code it will always be a list
   266   consisting of a single formula. Compare this tactic with the manual proof
   264   consisting of a single formula. Compare this tactic with the manual proof
   267   for the lemma @{thm [source] manual_ind_prin_even}: as you can see there is
   265   for the lemma @{thm [source] manual_ind_prin_even}: as you can see there is
   268   almost a one-to-one correspondence between the \isacommand{apply}-script and
   266   almost a one-to-one correspondence between the \isacommand{apply}-script and
   269   the @{ML ind_tac}. We first rewrite the goal to use only object connectives (Line 2),
   267   the @{ML ind_tac}. We first rewrite the goal to use only object connectives (Line 2),
   270   "cut in" the premise (Line 3), unfold the definitions (Line 4), instantiate
   268   "cut in" the premise (Line 3), unfold the definitions (Line 4), instantiate
   271   the assumptions of the goal (Line 5) and then conclude with @{ML assume_tac}.
   269   the assumptions of the goal (Line 5) and then conclude with @{ML assume_tac}.
   272 
   270 
   273   Two testcases for this tactic are:
   271   Two testcases for this tactic are:
   274 *}
   272 \<close>
   275 
   273 
   276 lemma automatic_ind_prin_even:
   274 lemma automatic_ind_prin_even:
   277 assumes prem: "even z"
   275 assumes prem: "even z"
   278 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   276 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   279 by (tactic {* ind_tac @{context} eo_defs @{thms prem} 
   277 by (tactic \<open>ind_tac @{context} eo_defs @{thms prem} 
   280                     [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] *})
   278                     [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]\<close>)
   281 
   279 
   282 lemma automatic_ind_prin_fresh:
   280 lemma automatic_ind_prin_fresh:
   283 assumes prem: "fresh z za" 
   281 assumes prem: "fresh z za" 
   284 shows "(\<And>a b. a \<noteq> b \<Longrightarrow> P a (Var b)) \<Longrightarrow> 
   282 shows "(\<And>a b. a \<noteq> b \<Longrightarrow> P a (Var b)) \<Longrightarrow> 
   285         (\<And>a t s. \<lbrakk>P a t; P a s\<rbrakk> \<Longrightarrow> P a (App t s)) \<Longrightarrow>
   283         (\<And>a t s. \<lbrakk>P a t; P a s\<rbrakk> \<Longrightarrow> P a (App t s)) \<Longrightarrow>
   286         (\<And>a t. P a (Lam a t)) \<Longrightarrow> 
   284         (\<And>a t. P a (Lam a t)) \<Longrightarrow> 
   287         (\<And>a b t. \<lbrakk>a \<noteq> b; P a t\<rbrakk> \<Longrightarrow> P a (Lam b t)) \<Longrightarrow> P z za"
   285         (\<And>a b t. \<lbrakk>a \<noteq> b; P a t\<rbrakk> \<Longrightarrow> P a (Lam b t)) \<Longrightarrow> P z za"
   288 by (tactic {* ind_tac @{context} @{thms fresh_def} @{thms prem} 
   286 by (tactic \<open>ind_tac @{context} @{thms fresh_def} @{thms prem} 
   289                           [@{cterm "P::string\<Rightarrow>trm\<Rightarrow>bool"}] *})
   287                           [@{cterm "P::string\<Rightarrow>trm\<Rightarrow>bool"}]\<close>)
   290 
   288 
   291 
   289 
   292 text {*
   290 text \<open>
   293   While the tactic for proving the induction principles is relatively simple,
   291   While the tactic for proving the induction principles is relatively simple,
   294   it will be a bit more work to construct the goals from the introduction rules
   292   it will be a bit more work to construct the goals from the introduction rules
   295   the user provides.  Therefore let us have a closer look at the first 
   293   the user provides.  Therefore let us have a closer look at the first 
   296   proved theorem:
   294   proved theorem:
   297 
   295 
   298   \begin{isabelle}
   296   \begin{isabelle}
   299   \isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\
   297   \isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\
   300   @{text "> "}~@{thm automatic_ind_prin_even}
   298   \<open>> \<close>~@{thm automatic_ind_prin_even}
   301   \end{isabelle}
   299   \end{isabelle}
   302 
   300 
   303   The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic
   301   The variables \<open>z\<close>, \<open>P\<close> and \<open>Q\<close> are schematic
   304   variables (since they are not quantified in the lemma). These 
   302   variables (since they are not quantified in the lemma). These 
   305   variables must be schematic, otherwise they cannot be instantiated 
   303   variables must be schematic, otherwise they cannot be instantiated 
   306   by the user. To generate these schematic variables we use a common trick
   304   by the user. To generate these schematic variables we use a common trick
   307   in Isabelle programming: we first declare them as \emph{free}, 
   305   in Isabelle programming: we first declare them as \emph{free}, 
   308   \emph{but fixed}, and then use the infrastructure to turn them into 
   306   \emph{but fixed}, and then use the infrastructure to turn them into 
   309   schematic variables.
   307   schematic variables.
   310 
   308 
   311   In general we have to construct for each predicate @{text "pred"} a goal 
   309   In general we have to construct for each predicate \<open>pred\<close> a goal 
   312   of the form
   310   of the form
   313 
   311 
   314   @{text [display] 
   312   @{text [display] 
   315   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
   313   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
   316 
   314 
   317   where the predicates @{text preds} are replaced in @{text rules} by new 
   315   where the predicates \<open>preds\<close> are replaced in \<open>rules\<close> by new 
   318   distinct variables @{text "?Ps"}. We also need to generate fresh arguments 
   316   distinct variables \<open>?Ps\<close>. We also need to generate fresh arguments 
   319   @{text "?zs"} for the predicate  @{text "pred"} and the @{text "?P"} in 
   317   \<open>?zs\<close> for the predicate  \<open>pred\<close> and the \<open>?P\<close> in 
   320   the conclusion. 
   318   the conclusion. 
   321 
   319 
   322   We generate these goals in two steps. The first function, named @{text prove_ind}, 
   320   We generate these goals in two steps. The first function, named \<open>prove_ind\<close>, 
   323   expects that the introduction rules are already appropriately substituted. The argument
   321   expects that the introduction rules are already appropriately substituted. The argument
   324   @{text "srules"} stands for these substituted rules; @{text cnewpreds} are
   322   \<open>srules\<close> stands for these substituted rules; \<open>cnewpreds\<close> are
   325   the certified terms coresponding to the variables @{text "?Ps"}; @{text
   323   the certified terms coresponding to the variables \<open>?Ps\<close>; \<open>pred\<close> is the predicate for which we prove the induction principle;
   326   "pred"} is the predicate for which we prove the induction principle;
   324   \<open>newpred\<close> is its replacement and \<open>arg_tys\<close> are the argument
   327   @{text "newpred"} is its replacement and @{text "arg_tys"} are the argument
       
   328   types of this predicate.
   325   types of this predicate.
   329 *}
   326 \<close>
   330 
   327 
   331 ML %linenosgray{*fun prove_ind lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
   328 ML %linenosgray\<open>fun prove_ind lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
   332 let
   329 let
   333   val zs = replicate (length arg_tys) "z"
   330   val zs = replicate (length arg_tys) "z"
   334   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   331   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   335   val newargs = map Free (newargnames ~~ arg_tys)
   332   val newargs = map Free (newargnames ~~ arg_tys)
   336   
   333   
   339          (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   336          (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   340 in
   337 in
   341   Goal.prove lthy' [] [prem] goal
   338   Goal.prove lthy' [] [prem] goal
   342       (fn {prems, context, ...} => ind_tac context defs prems cnewpreds)
   339       (fn {prems, context, ...} => ind_tac context defs prems cnewpreds)
   343   |> singleton (Proof_Context.export lthy' lthy)
   340   |> singleton (Proof_Context.export lthy' lthy)
   344 end *}
   341 end\<close>
   345 
   342 
   346 text {* 
   343 text \<open>
   347   In Line 3 we produce names @{text "zs"} for each type in the 
   344   In Line 3 we produce names \<open>zs\<close> for each type in the 
   348   argument type list. Line 4 makes these names unique and declares them as 
   345   argument type list. Line 4 makes these names unique and declares them as 
   349   free, but fixed, variables in the local theory @{text "lthy'"}. 
   346   free, but fixed, variables in the local theory \<open>lthy'\<close>. 
   350   That means they are not schematic variables (yet).
   347   That means they are not schematic variables (yet).
   351   In Line 5 we construct the terms corresponding to these variables. 
   348   In Line 5 we construct the terms corresponding to these variables. 
   352   The variables are applied to the predicate in Line 7 (this corresponds
   349   The variables are applied to the predicate in Line 7 (this corresponds
   353   to the first premise @{text "pred zs"} of the induction principle). 
   350   to the first premise \<open>pred zs\<close> of the induction principle). 
   354   In Line 8 and 9, we first construct the term  @{text "P zs"} 
   351   In Line 8 and 9, we first construct the term  \<open>P zs\<close> 
   355   and then add the (substituted) introduction rules as preconditions. In 
   352   and then add the (substituted) introduction rules as preconditions. In 
   356   case that no introduction rules are given, the conclusion of this 
   353   case that no introduction rules are given, the conclusion of this 
   357   implication needs to be wrapped inside a @{term Trueprop}, otherwise 
   354   implication needs to be wrapped inside a @{term Trueprop}, otherwise 
   358   the Isabelle's goal mechanism will fail.\footnote{FIXME: check with 
   355   the Isabelle's goal mechanism will fail.\footnote{FIXME: check with 
   359   Stefan...is this so?} 
   356   Stefan...is this so?} 
   362   prove in Goal}; in the next line we call the tactic for proving the
   359   prove in Goal}; in the next line we call the tactic for proving the
   363   induction principle. As mentioned before, this tactic expects the
   360   induction principle. As mentioned before, this tactic expects the
   364   definitions, the premise and the (certified) predicates with which the
   361   definitions, the premise and the (certified) predicates with which the
   365   introduction rules have been substituted. The code in these two lines will
   362   introduction rules have been substituted. The code in these two lines will
   366   return a theorem. However, it is a theorem proved inside the local theory
   363   return a theorem. However, it is a theorem proved inside the local theory
   367   @{text "lthy'"}, where the variables @{text "zs"} are free, but fixed (see
   364   \<open>lthy'\<close>, where the variables \<open>zs\<close> are free, but fixed (see
   368   Line 4). By exporting this theorem from @{text "lthy'"} (which contains the
   365   Line 4). By exporting this theorem from \<open>lthy'\<close> (which contains the
   369   @{text "zs"} as free variables) to @{text "lthy"} (which does not), we
   366   \<open>zs\<close> as free variables) to \<open>lthy\<close> (which does not), we
   370   obtain the desired schematic variables @{text "?zs"}.  A testcase for this
   367   obtain the desired schematic variables \<open>?zs\<close>.  A testcase for this
   371   function is
   368   function is
   372 *}
   369 \<close>
   373 
   370 
   374 local_setup %gray {* fn lthy =>
   371 local_setup %gray \<open>fn lthy =>
   375 let
   372 let
   376   val newpreds = [@{term "P::nat \<Rightarrow> bool"}, @{term "Q::nat \<Rightarrow> bool"}]
   373   val newpreds = [@{term "P::nat \<Rightarrow> bool"}, @{term "Q::nat \<Rightarrow> bool"}]
   377   val cnewpreds = [@{cterm "P::nat \<Rightarrow> bool"}, @{cterm "Q::nat \<Rightarrow> bool"}]
   374   val cnewpreds = [@{cterm "P::nat \<Rightarrow> bool"}, @{cterm "Q::nat \<Rightarrow> bool"}]
   378   val newpred = @{term "P::nat \<Rightarrow> bool"}
   375   val newpred = @{term "P::nat \<Rightarrow> bool"}
   379   val srules =  map (subst_free (eo_preds ~~ newpreds)) eo_rules
   376   val srules =  map (subst_free (eo_preds ~~ newpreds)) eo_rules
   380   val intro = 
   377   val intro = 
   381       prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys)
   378       prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys)
   382 in
   379 in
   383   pwriteln (pretty_thm lthy intro); lthy
   380   pwriteln (pretty_thm lthy intro); lthy
   384 end *}
   381 end\<close>
   385 
   382 
   386 text {*
   383 text \<open>
   387   This prints out the theorem:
   384   This prints out the theorem:
   388 
   385 
   389   @{text [display]
   386   @{text [display]
   390   " \<lbrakk>even ?z; P 0; \<And>n. Q n \<Longrightarrow> P (Suc n); \<And>n. P n \<Longrightarrow> Q (Suc n)\<rbrakk> \<Longrightarrow> P ?z"}
   387   " \<lbrakk>even ?z; P 0; \<And>n. Q n \<Longrightarrow> P (Suc n); \<And>n. P n \<Longrightarrow> Q (Suc n)\<rbrakk> \<Longrightarrow> P ?z"}
   391 
   388 
   392   The export from @{text lthy'} to @{text lthy} in Line 13 above 
   389   The export from \<open>lthy'\<close> to \<open>lthy\<close> in Line 13 above 
   393   has correctly turned the free, but fixed, @{text "z"} into a schematic 
   390   has correctly turned the free, but fixed, \<open>z\<close> into a schematic 
   394   variable @{text "?z"}; the variables @{text "P"} and @{text "Q"} are not yet
   391   variable \<open>?z\<close>; the variables \<open>P\<close> and \<open>Q\<close> are not yet
   395   schematic. 
   392   schematic. 
   396 
   393 
   397   We still have to produce the new predicates with which the introduction
   394   We still have to produce the new predicates with which the introduction
   398   rules are substituted and iterate @{ML prove_ind} over all
   395   rules are substituted and iterate @{ML prove_ind} over all
   399   predicates. This is what the second function, named @{text inds} does. 
   396   predicates. This is what the second function, named \<open>inds\<close> does. 
   400 *}
   397 \<close>
   401 
   398 
   402 ML %linenosgray{*fun inds rules defs preds arg_tyss lthy  =
   399 ML %linenosgray\<open>fun inds rules defs preds arg_tyss lthy  =
   403 let
   400 let
   404   val Ps = replicate (length preds) "P"
   401   val Ps = replicate (length preds) "P"
   405   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   402   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   406   
   403   
   407   val tyss' = map (fn tys => tys ---> HOLogic.boolT) arg_tyss
   404   val tyss' = map (fn tys => tys ---> HOLogic.boolT) arg_tyss
   411 
   408 
   412 in
   409 in
   413   map (prove_ind lthy' defs srules cnewpreds) 
   410   map (prove_ind lthy' defs srules cnewpreds) 
   414         (preds ~~ newpreds ~~ arg_tyss)
   411         (preds ~~ newpreds ~~ arg_tyss)
   415           |> Proof_Context.export lthy' lthy
   412           |> Proof_Context.export lthy' lthy
   416 end*}
   413 end\<close>
   417 
   414 
   418 text {*
   415 text \<open>
   419   In Line 3, we generate a string @{text [quotes] "P"} for each predicate. 
   416   In Line 3, we generate a string @{text [quotes] "P"} for each predicate. 
   420   In Line 4, we use the same trick as in the previous function, that is making the 
   417   In Line 4, we use the same trick as in the previous function, that is making the 
   421   @{text "Ps"} fresh and declaring them as free, but fixed, in
   418   \<open>Ps\<close> fresh and declaring them as free, but fixed, in
   422   the new local theory @{text "lthy'"}. In Line 6, we construct the types of these new predicates
   419   the new local theory \<open>lthy'\<close>. In Line 6, we construct the types of these new predicates
   423   using the given argument types. Next we turn them into terms and subsequently
   420   using the given argument types. Next we turn them into terms and subsequently
   424   certify them (Line 7 and 8). We can now produce the substituted introduction rules 
   421   certify them (Line 7 and 8). We can now produce the substituted introduction rules 
   425   (Line 9) using the function @{ML_ind subst_free in Term}. Line 12 and 13 just iterate 
   422   (Line 9) using the function @{ML_ind subst_free in Term}. Line 12 and 13 just iterate 
   426   the proofs for all predicates.
   423   the proofs for all predicates.
   427   From this we obtain a list of theorems. Finally we need to export the 
   424   From this we obtain a list of theorems. Finally we need to export the 
   428   fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"} 
   425   fixed variables \<open>Ps\<close> to obtain the schematic variables \<open>?Ps\<close> 
   429   (Line 14).
   426   (Line 14).
   430 
   427 
   431   A testcase for this function is
   428   A testcase for this function is
   432 *}
   429 \<close>
   433 
   430 
   434 local_setup %gray {* fn lthy =>
   431 local_setup %gray \<open>fn lthy =>
   435 let 
   432 let 
   436   val ind_thms = inds eo_rules eo_defs eo_preds eo_arg_tyss lthy
   433   val ind_thms = inds eo_rules eo_defs eo_preds eo_arg_tyss lthy
   437 in
   434 in
   438   pwriteln (pretty_thms lthy ind_thms); lthy
   435   pwriteln (pretty_thms lthy ind_thms); lthy
   439 end *}
   436 end\<close>
   440 
   437 
   441 
   438 
   442 text {*
   439 text \<open>
   443   which prints out
   440   which prints out
   444 
   441 
   445 @{text [display]
   442 @{text [display]
   446 "even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   443 "even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   447  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   444  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   448 odd ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
   445 odd ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
   449  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   446  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   450 
   447 
   451   Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic
   448   Note that now both, the \<open>?Ps\<close> and the \<open>?zs\<close>, are schematic
   452   variables. The numbers attached to these variables have been introduced by 
   449   variables. The numbers attached to these variables have been introduced by 
   453   the pretty-printer and are \emph{not} important for the user. 
   450   the pretty-printer and are \emph{not} important for the user. 
   454 
   451 
   455   This completes the code for the induction principles. The final peice
   452   This completes the code for the induction principles. The final peice
   456   of reasoning infrastructure we need are the introduction rules. 
   453   of reasoning infrastructure we need are the introduction rules. 
   457 *}
   454 \<close>
   458 
   455 
   459 subsection {* Introduction Rules *}
   456 subsection \<open>Introduction Rules\<close>
   460 
   457 
   461 text {*
   458 text \<open>
   462   Constructing the goals for the introduction rules is easy: they
   459   Constructing the goals for the introduction rules is easy: they
   463   are just the rules given by the user. However, their proofs are 
   460   are just the rules given by the user. However, their proofs are 
   464   quite a bit more involved than the ones for the induction principles. 
   461   quite a bit more involved than the ones for the induction principles. 
   465   To explain the general method, our running example will be
   462   To explain the general method, our running example will be
   466   the introduction rule
   463   the introduction rule
   469   @{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"}
   466   @{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"}
   470   \end{isabelle}
   467   \end{isabelle}
   471   
   468   
   472   about freshness for lambdas. In order to ease somewhat 
   469   about freshness for lambdas. In order to ease somewhat 
   473   our work here, we use the following two helper functions.
   470   our work here, we use the following two helper functions.
   474 *}
   471 \<close>
   475 
   472 
   476 ML %grayML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   473 ML %grayML\<open>val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   477 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*}
   474 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})\<close>
   478 
   475 
   479 text {* 
   476 text \<open>
   480   To see what these functions do, let us suppose we have the following three
   477   To see what these functions do, let us suppose we have the following three
   481   theorems. 
   478   theorems. 
   482 *}
   479 \<close>
   483 
   480 
   484 lemma all_elims_test:
   481 lemma all_elims_test:
   485 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   482 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   486 shows "\<forall>x y z. P x y z" sorry
   483 shows "\<forall>x y z. P x y z" sorry
   487 
   484 
   489 shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   486 shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   490 
   487 
   491 lemma imp_elims_test':
   488 lemma imp_elims_test':
   492 shows "A" "B" sorry
   489 shows "A" "B" sorry
   493 
   490 
   494 text {*
   491 text \<open>
   495   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   492   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   496   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   493   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   497   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
   494   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
   498 
   495 
   499   @{ML_response_fake [display, gray]
   496   @{ML_response_fake [display, gray]
   508   Note the difference with @{ML inst_spec_tac} from Page~\pageref{fun:instspectac}:
   505   Note the difference with @{ML inst_spec_tac} from Page~\pageref{fun:instspectac}:
   509   @{ML inst_spec_tac} is a tactic which operates on a goal state; in contrast
   506   @{ML inst_spec_tac} is a tactic which operates on a goal state; in contrast
   510   @{ML all_elims} operates on theorems. 
   507   @{ML all_elims} operates on theorems. 
   511 
   508 
   512   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   509   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   513   For example we can eliminate the preconditions @{text "A"} and @{text "B"} from
   510   For example we can eliminate the preconditions \<open>A\<close> and \<open>B\<close> from
   514   @{thm [source] imp_elims_test}:
   511   @{thm [source] imp_elims_test}:
   515 
   512 
   516   @{ML_response_fake [display, gray]
   513   @{ML_response_fake [display, gray]
   517 "let
   514 "let
   518   val res = imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}
   515   val res = imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}
   520   pwriteln (pretty_thm_no_vars @{context} res)
   517   pwriteln (pretty_thm_no_vars @{context} res)
   521 end"
   518 end"
   522   "C"}
   519   "C"}
   523 
   520 
   524   Now we set up the proof for the introduction rule as follows:
   521   Now we set up the proof for the introduction rule as follows:
   525 *}
   522 \<close>
   526 
   523 
   527 lemma fresh_Lam:
   524 lemma fresh_Lam:
   528 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   525 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   529 (*<*)oops(*>*)
   526 (*<*)oops(*>*)
   530 
   527 
   531 text {*
   528 text \<open>
   532   The first step in the proof will be to expand the definitions of freshness
   529   The first step in the proof will be to expand the definitions of freshness
   533   and then introduce quantifiers and implications. For this we
   530   and then introduce quantifiers and implications. For this we
   534   will use the tactic
   531   will use the tactic
   535 *}
   532 \<close>
   536 
   533 
   537 ML %linenosgray{*fun expand_tac ctxt defs =
   534 ML %linenosgray\<open>fun expand_tac ctxt defs =
   538   Object_Logic.rulify_tac ctxt 1
   535   Object_Logic.rulify_tac ctxt 1
   539   THEN rewrite_goal_tac ctxt defs 1
   536   THEN rewrite_goal_tac ctxt defs 1
   540   THEN (REPEAT (resolve_tac ctxt [@{thm allI}, @{thm impI}] 1)) *}
   537   THEN (REPEAT (resolve_tac ctxt [@{thm allI}, @{thm impI}] 1))\<close>
   541 
   538 
   542 text {*
   539 text \<open>
   543   The function in Line 2 ``rulifies'' the lemma.\footnote{FIXME: explain this better} 
   540   The function in Line 2 ``rulifies'' the lemma.\footnote{FIXME: explain this better} 
   544   This will turn out to 
   541   This will turn out to 
   545   be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
   542   be important later on. Applying this tactic in our proof of \<open>fresh_Lem\<close>
   546 *}
   543 \<close>
   547 
   544 
   548 (*<*)
   545 (*<*)
   549 lemma fresh_Lam:
   546 lemma fresh_Lam:
   550 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   547 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   551 (*>*)
   548 (*>*)
   552 apply(tactic {* expand_tac @{context} @{thms fresh_def} *})
   549 apply(tactic \<open>expand_tac @{context} @{thms fresh_def}\<close>)
   553 
   550 
   554 txt {*
   551 txt \<open>
   555   gives us the goal state
   552   gives us the goal state
   556 
   553 
   557   \begin{isabelle}
   554   \begin{isabelle}
   558   @{subgoals [display]}
   555   @{subgoals [display]}
   559   \end{isabelle}
   556   \end{isabelle}
   560 
   557 
   561   As you can see, there are parameters (namely @{text "a"}, @{text "b"} and
   558   As you can see, there are parameters (namely \<open>a\<close>, \<open>b\<close> and
   562   @{text "t"}) which come from the introduction rule and parameters (in the
   559   \<open>t\<close>) which come from the introduction rule and parameters (in the
   563   case above only @{text "fresh"}) which come from the universal
   560   case above only \<open>fresh\<close>) which come from the universal
   564   quantification in the definition @{term "fresh a (App t s)"}.  Similarly,
   561   quantification in the definition @{term "fresh a (App t s)"}.  Similarly,
   565   there are assumptions that come from the premises of the rule (namely the
   562   there are assumptions that come from the premises of the rule (namely the
   566   first two) and assumptions from the definition of the predicate (assumption
   563   first two) and assumptions from the definition of the predicate (assumption
   567   three to six). We need to treat these parameters and assumptions
   564   three to six). We need to treat these parameters and assumptions
   568   differently. In the code below we will therefore separate them into @{text
   565   differently. In the code below we will therefore separate them into \<open>params1\<close> and \<open>params2\<close>, respectively \<open>prems1\<close> and \<open>prems2\<close>. To do this separation, it is best to open a subproof with the
   569   "params1"} and @{text params2}, respectively @{text "prems1"} and @{text
       
   570   "prems2"}. To do this separation, it is best to open a subproof with the
       
   571   tactic @{ML_ind SUBPROOF in Subgoal}, since this tactic provides us with the parameters (as
   566   tactic @{ML_ind SUBPROOF in Subgoal}, since this tactic provides us with the parameters (as
   572   list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s). 
   567   list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s). 
   573   The problem with @{ML SUBPROOF}, however, is that it always expects us to 
   568   The problem with @{ML SUBPROOF}, however, is that it always expects us to 
   574   completely discharge the goal (see Section~\ref{sec:simpletacs}). This is 
   569   completely discharge the goal (see Section~\ref{sec:simpletacs}). This is 
   575   a bit inconvenient for our gradual explanation of the proof here. Therefore
   570   a bit inconvenient for our gradual explanation of the proof here. Therefore
   576   we use first the function @{ML_ind  FOCUS in Subgoal}, which does s
   571   we use first the function @{ML_ind  FOCUS in Subgoal}, which does s
   577   ame as @{ML SUBPROOF} 
   572   ame as @{ML SUBPROOF} 
   578   but does not require us to completely discharge the goal. 
   573   but does not require us to completely discharge the goal. 
   579 *}
   574 \<close>
   580 (*<*)oops(*>*)
   575 (*<*)oops(*>*)
   581 text_raw {*
   576 text_raw \<open>
   582 \begin{figure}[t]
   577 \begin{figure}[t]
   583 \begin{minipage}{\textwidth}
   578 \begin{minipage}{\textwidth}
   584 \begin{isabelle}
   579 \begin{isabelle}
   585 *}
   580 \<close>
   586 ML %grayML{*fun chop_print params1 params2 prems1 prems2 ctxt =
   581 ML %grayML\<open>fun chop_print params1 params2 prems1 prems2 ctxt =
   587 let 
   582 let 
   588  val pps = [Pretty.big_list "Params1 from the rule:" (map (pretty_cterm ctxt) params1), 
   583  val pps = [Pretty.big_list "Params1 from the rule:" (map (pretty_cterm ctxt) params1), 
   589             Pretty.big_list "Params2 from the predicate:" (map (pretty_cterm ctxt) params2), 
   584             Pretty.big_list "Params2 from the predicate:" (map (pretty_cterm ctxt) params2), 
   590             Pretty.big_list "Prems1 from the rule:" (map (pretty_thm ctxt) prems1),
   585             Pretty.big_list "Prems1 from the rule:" (map (pretty_thm ctxt) prems1),
   591             Pretty.big_list "Prems2 from the predicate:" (map (pretty_thm ctxt) prems2)] 
   586             Pretty.big_list "Prems2 from the predicate:" (map (pretty_thm ctxt) prems2)] 
   592 in 
   587 in 
   593   pps |> Pretty.chunks
   588   pps |> Pretty.chunks
   594       |> Pretty.string_of
   589       |> Pretty.string_of
   595       |> tracing
   590       |> tracing
   596 end*}
   591 end\<close>
   597 
   592 
   598 text_raw{*
   593 text_raw\<open>
   599 \end{isabelle}
   594 \end{isabelle}
   600 \end{minipage}
   595 \end{minipage}
   601 \caption{A helper function that prints out the parameters and premises that
   596 \caption{A helper function that prints out the parameters and premises that
   602   need to be treated differently.\label{fig:chopprint}}
   597   need to be treated differently.\label{fig:chopprint}}
   603 \end{figure}
   598 \end{figure}
   604 *}
   599 \<close>
   605 
   600 
   606 text {*
   601 text \<open>
   607   First we calculate the values for @{text "params1/2"} and @{text "prems1/2"}
   602   First we calculate the values for \<open>params1/2\<close> and \<open>prems1/2\<close>
   608   from @{text "params"} and @{text "prems"}, respectively. To better see what is
   603   from \<open>params\<close> and \<open>prems\<close>, respectively. To better see what is
   609   going in our example, we will print out these values using the printing
   604   going in our example, we will print out these values using the printing
   610   function in Figure~\ref{fig:chopprint}. Since @{ML FOCUS in Subgoal} will
   605   function in Figure~\ref{fig:chopprint}. Since @{ML FOCUS in Subgoal} will
   611   supply us the @{text "params"} and @{text "prems"} as lists, we can 
   606   supply us the \<open>params\<close> and \<open>prems\<close> as lists, we can 
   612   separate them using the function @{ML_ind chop in Library}. 
   607   separate them using the function @{ML_ind chop in Library}. 
   613 *}
   608 \<close>
   614 
   609 
   615 ML %linenosgray{*fun chop_test_tac preds rules =
   610 ML %linenosgray\<open>fun chop_test_tac preds rules =
   616   Subgoal.FOCUS (fn {params, prems, context, ...} =>
   611   Subgoal.FOCUS (fn {params, prems, context, ...} =>
   617   let
   612   let
   618     val cparams = map snd params
   613     val cparams = map snd params
   619     val (params1, params2) = chop (length cparams - length preds) cparams
   614     val (params1, params2) = chop (length cparams - length preds) cparams
   620     val (prems1, prems2) = chop (length prems - length rules) prems
   615     val (prems1, prems2) = chop (length prems - length rules) prems
   621   in
   616   in
   622     chop_print params1 params2 prems1 prems2 context; all_tac
   617     chop_print params1 params2 prems1 prems2 context; all_tac
   623   end) *}
   618   end)\<close>
   624 
   619 
   625 text {* 
   620 text \<open>
   626   For the separation we can rely on the fact that Isabelle deterministically 
   621   For the separation we can rely on the fact that Isabelle deterministically 
   627   produces parameters and premises in a goal state. The last parameters
   622   produces parameters and premises in a goal state. The last parameters
   628   that were introduced come from the quantifications in the definitions
   623   that were introduced come from the quantifications in the definitions
   629   (see the tactic @{ML expand_tac}).
   624   (see the tactic @{ML expand_tac}).
   630   Therefore we only have to subtract in Line 5 the number of predicates (in this
   625   Therefore we only have to subtract in Line 5 the number of predicates (in this
   631   case only @{text "1"}) from the lenghts of all parameters. Similarly
   626   case only \<open>1\<close>) from the lenghts of all parameters. Similarly
   632   with the @{text "prems"} in line 6: the last premises in the goal state come from 
   627   with the \<open>prems\<close> in line 6: the last premises in the goal state come from 
   633   unfolding the definition of the predicate in the conclusion. So we can 
   628   unfolding the definition of the predicate in the conclusion. So we can 
   634   just subtract the number of rules from the number of all premises. 
   629   just subtract the number of rules from the number of all premises. 
   635   To check our calculations we print them out in Line 8 using the
   630   To check our calculations we print them out in Line 8 using the
   636   function @{ML chop_print} from Figure~\ref{fig:chopprint} and then 
   631   function @{ML chop_print} from Figure~\ref{fig:chopprint} and then 
   637   just do nothing, that is @{ML all_tac}. Applying this tactic in our example 
   632   just do nothing, that is @{ML all_tac}. Applying this tactic in our example 
   638 *}
   633 \<close>
   639 
   634 
   640 (*<*)
   635 (*<*)
   641 lemma fresh_Lam:
   636 lemma fresh_Lam:
   642 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   637 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   643 apply(tactic {* expand_tac @{context} @{thms fresh_def} *})
   638 apply(tactic \<open>expand_tac @{context} @{thms fresh_def}\<close>)
   644 (*>*)
   639 (*>*)
   645 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} 1 *})
   640 apply(tactic \<open>chop_test_tac [fresh_pred] fresh_rules @{context} 1\<close>)
   646 (*<*)oops(*>*)
   641 (*<*)oops(*>*)
   647 
   642 
   648 text {*
   643 text \<open>
   649   gives
   644   gives
   650 
   645 
   651   \begin{isabelle}
   646   \begin{isabelle}
   652   @{text "Params1 from the rule:"}\\
   647   \<open>Params1 from the rule:\<close>\\
   653   @{text "a, b, t"}\\
   648   \<open>a, b, t\<close>\\
   654   @{text "Params2 from the predicate:"}\\
   649   \<open>Params2 from the predicate:\<close>\\
   655   @{text "fresh"}\\
   650   \<open>fresh\<close>\\
   656   @{text "Prems1 from the rule:"}\\
   651   \<open>Prems1 from the rule:\<close>\\
   657   @{term "a \<noteq> b"}\\
   652   @{term "a \<noteq> b"}\\
   658   @{text [break]
   653   @{text [break]
   659 "\<forall>fresh.
   654 "\<forall>fresh.
   660       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   655       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   661       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   656       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   662       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
   657       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
   663       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}\\
   658       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}\\
   664    @{text "Prems2 from the predicate:"}\\
   659    \<open>Prems2 from the predicate:\<close>\\
   665    @{term "\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)"}\\
   660    @{term "\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)"}\\
   666    @{term "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"}\\
   661    @{term "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"}\\
   667    @{term "\<forall>a t. fresh a (Lam a t)"}\\
   662    @{term "\<forall>a t. fresh a (Lam a t)"}\\
   668    @{term "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)"}
   663    @{term "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)"}
   669   \end{isabelle}
   664   \end{isabelle}
   670 
   665 
   671 
   666 
   672   We now have to select from @{text prems2} the premise 
   667   We now have to select from \<open>prems2\<close> the premise 
   673   that corresponds to the introduction rule we prove, namely:
   668   that corresponds to the introduction rule we prove, namely:
   674 
   669 
   675   @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"}
   670   @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"}
   676 
   671 
   677   To use this premise with @{ML resolve_tac}, we need to instantiate its 
   672   To use this premise with @{ML resolve_tac}, we need to instantiate its 
   678   quantifiers (with @{text params1}) and transform it into rule 
   673   quantifiers (with \<open>params1\<close>) and transform it into rule 
   679   format (using @{ML_ind  rulify in Object_Logic}). So we can modify the 
   674   format (using @{ML_ind  rulify in Object_Logic}). So we can modify the 
   680   code as follows:
   675   code as follows:
   681 *}
   676 \<close>
   682 
   677 
   683 ML %linenosgray{*fun apply_prem_tac i preds rules =
   678 ML %linenosgray\<open>fun apply_prem_tac i preds rules =
   684   Subgoal.FOCUS (fn {params, prems, context, ...} =>
   679   Subgoal.FOCUS (fn {params, prems, context, ...} =>
   685   let
   680   let
   686     val cparams = map snd params
   681     val cparams = map snd params
   687     val (params1, params2) = chop (length cparams - length preds) cparams
   682     val (params1, params2) = chop (length cparams - length preds) cparams
   688     val (prems1, prems2) = chop (length prems - length rules) prems
   683     val (prems1, prems2) = chop (length prems - length rules) prems
   689   in
   684   in
   690     resolve_tac  context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   685     resolve_tac  context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   691   end) *}
   686   end)\<close>
   692 
   687 
   693 text {* 
   688 text \<open>
   694   The argument @{text i} corresponds to the number of the 
   689   The argument \<open>i\<close> corresponds to the number of the 
   695   introduction we want to prove. We will later on let it range
   690   introduction we want to prove. We will later on let it range
   696   from @{text 0} to the number of @{text "rules - 1"}.
   691   from \<open>0\<close> to the number of \<open>rules - 1\<close>.
   697   Below we apply this function with @{text 3}, since 
   692   Below we apply this function with \<open>3\<close>, since 
   698   we are proving the fourth introduction rule. 
   693   we are proving the fourth introduction rule. 
   699 *}
   694 \<close>
   700 
   695 
   701 (*<*)
   696 (*<*)
   702 lemma fresh_Lam:
   697 lemma fresh_Lam:
   703 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   698 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   704 apply(tactic {* expand_tac @{context} @{thms fresh_def} *})
   699 apply(tactic \<open>expand_tac @{context} @{thms fresh_def}\<close>)
   705 (*>*)
   700 (*>*)
   706 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} 1 *})
   701 apply(tactic \<open>apply_prem_tac 3 [fresh_pred] fresh_rules @{context} 1\<close>)
   707 (*<*)oops(*>*)
   702 (*<*)oops(*>*)
   708 
   703 
   709 text {*
   704 text \<open>
   710   The goal state we obtain is: 
   705   The goal state we obtain is: 
   711 
   706 
   712   \begin{isabelle}
   707   \begin{isabelle}
   713   @{text "1."}~@{text "\<dots> \<Longrightarrow> "}~@{prop "a \<noteq> b"}\\
   708   \<open>1.\<close>~\<open>\<dots> \<Longrightarrow> \<close>~@{prop "a \<noteq> b"}\\
   714   @{text "2."}~@{text "\<dots> \<Longrightarrow> "}~@{prop "fresh a t"}
   709   \<open>2.\<close>~\<open>\<dots> \<Longrightarrow> \<close>~@{prop "fresh a t"}
   715   \end{isabelle}
   710   \end{isabelle}
   716 
   711 
   717   As expected there are two subgoals, where the first comes from the
   712   As expected there are two subgoals, where the first comes from the
   718   non-recursive premise of the introduction rule and the second comes 
   713   non-recursive premise of the introduction rule and the second comes 
   719   from the recursive one. The first goal can be solved immediately 
   714   from the recursive one. The first goal can be solved immediately 
   720   by @{text "prems1"}. The second needs more work. It can be solved 
   715   by \<open>prems1\<close>. The second needs more work. It can be solved 
   721   with the other premise in @{text "prems1"}, namely
   716   with the other premise in \<open>prems1\<close>, namely
   722 
   717 
   723 
   718 
   724   @{term [break,display]
   719   @{term [break,display]
   725   "\<forall>fresh.
   720   "\<forall>fresh.
   726       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   721       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
   727       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   722       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
   728       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
   723       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
   729       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}
   724       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}
   730 
   725 
   731   but we have to instantiate it appropriately. These instantiations
   726   but we have to instantiate it appropriately. These instantiations
   732   come from @{text "params1"} and @{text "prems2"}. We can determine
   727   come from \<open>params1\<close> and \<open>prems2\<close>. We can determine
   733   whether we are in the simple or complicated case by checking whether
   728   whether we are in the simple or complicated case by checking whether
   734   the topmost connective is an @{text "\<forall>"}. The premises in the simple
   729   the topmost connective is an \<open>\<forall>\<close>. The premises in the simple
   735   case cannot have such a quantification, since the first step 
   730   case cannot have such a quantification, since the first step 
   736   of @{ML "expand_tac"} was to ``rulify'' the lemma. 
   731   of @{ML "expand_tac"} was to ``rulify'' the lemma. 
   737   The premise of the complicated case must have at least one  @{text "\<forall>"}
   732   The premise of the complicated case must have at least one  \<open>\<forall>\<close>
   738   coming from the quantification over the @{text preds}. So 
   733   coming from the quantification over the \<open>preds\<close>. So 
   739   we can implement the following function
   734   we can implement the following function
   740 *}
   735 \<close>
   741 
   736 
   742 ML %grayML{*fun prepare_prem ctxt params2 prems2 prem =  
   737 ML %grayML\<open>fun prepare_prem ctxt params2 prems2 prem =  
   743   resolve_tac ctxt [case Thm.prop_of prem of
   738   resolve_tac ctxt [case Thm.prop_of prem of
   744            _ $ (Const (@{const_name All}, _) $ _) =>
   739            _ $ (Const (@{const_name All}, _) $ _) =>
   745                  prem |> all_elims params2 
   740                  prem |> all_elims params2 
   746                       |> imp_elims prems2
   741                       |> imp_elims prems2
   747          | _ => prem] *}
   742          | _ => prem]\<close>
   748 
   743 
   749 text {* 
   744 text \<open>
   750   which either applies the premise outright (the default case) or if 
   745   which either applies the premise outright (the default case) or if 
   751   it has an outermost universial quantification, instantiates it first 
   746   it has an outermost universial quantification, instantiates it first 
   752   with  @{text "params1"} and then @{text "prems1"}. The following 
   747   with  \<open>params1\<close> and then \<open>prems1\<close>. The following 
   753   tactic will therefore prove the lemma completely.
   748   tactic will therefore prove the lemma completely.
   754 *}
   749 \<close>
   755 
   750 
   756 ML %grayML{*fun prove_intro_tac i preds rules =
   751 ML %grayML\<open>fun prove_intro_tac i preds rules =
   757   SUBPROOF (fn {params, prems, context, ...} =>
   752   SUBPROOF (fn {params, prems, context, ...} =>
   758   let
   753   let
   759     val cparams = map snd params
   754     val cparams = map snd params
   760     val (params1, params2) = chop (length cparams - length preds) cparams
   755     val (params1, params2) = chop (length cparams - length preds) cparams
   761     val (prems1, prems2) = chop (length prems - length rules) prems
   756     val (prems1, prems2) = chop (length prems - length rules) prems
   762   in
   757   in
   763     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   758     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   764     THEN EVERY1 (map (prepare_prem context params2 prems2) prems1)
   759     THEN EVERY1 (map (prepare_prem context params2 prems2) prems1)
   765   end) *}
   760   end)\<close>
   766 
   761 
   767 text {*
   762 text \<open>
   768   Note that the tactic is now @{ML SUBPROOF}, not @{ML FOCUS in Subgoal} anymore. 
   763   Note that the tactic is now @{ML SUBPROOF}, not @{ML FOCUS in Subgoal} anymore. 
   769   The full proof of the introduction rule is as follows:
   764   The full proof of the introduction rule is as follows:
   770 *}
   765 \<close>
   771 
   766 
   772 lemma fresh_Lam:
   767 lemma fresh_Lam:
   773 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   768 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   774 apply(tactic {* expand_tac @{context} @{thms fresh_def} *})
   769 apply(tactic \<open>expand_tac @{context} @{thms fresh_def}\<close>)
   775 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *})
   770 apply(tactic \<open>prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1\<close>)
   776 done
   771 done
   777 
   772 
   778 text {* 
   773 text \<open>
   779   Phew!\ldots  
   774   Phew!\ldots  
   780 
   775 
   781   Unfortunately, not everything is done yet. If you look closely
   776   Unfortunately, not everything is done yet. If you look closely
   782   at the general principle outlined for the introduction rules in 
   777   at the general principle outlined for the introduction rules in 
   783   Section~\ref{sec:nutshell}, we have  not yet dealt with the case where 
   778   Section~\ref{sec:nutshell}, we have  not yet dealt with the case where 
   784   recursive premises have preconditions. The introduction rule
   779   recursive premises have preconditions. The introduction rule
   785   of the accessible part is such a rule. 
   780   of the accessible part is such a rule. 
   786 *}
   781 \<close>
   787 
   782 
   788 
   783 
   789 lemma accpartI:
   784 lemma accpartI:
   790 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   785 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   791 apply(tactic {* expand_tac @{context} @{thms accpart_def} *})
   786 apply(tactic \<open>expand_tac @{context} @{thms accpart_def}\<close>)
   792 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} 1 *})
   787 apply(tactic \<open>chop_test_tac [acc_pred] acc_rules @{context} 1\<close>)
   793 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} 1 *})
   788 apply(tactic \<open>apply_prem_tac 0 [acc_pred] acc_rules @{context} 1\<close>)
   794 
   789 
   795 txt {*
   790 txt \<open>
   796   Here @{ML chop_test_tac} prints out the following
   791   Here @{ML chop_test_tac} prints out the following
   797   values for @{text "params1/2"} and @{text "prems1/2"}
   792   values for \<open>params1/2\<close> and \<open>prems1/2\<close>
   798 
   793 
   799   \begin{isabelle}
   794   \begin{isabelle}
   800   @{text "Params1 from the rule:"}\\
   795   \<open>Params1 from the rule:\<close>\\
   801   @{text "x"}\\
   796   \<open>x\<close>\\
   802   @{text "Params2 from the predicate:"}\\
   797   \<open>Params2 from the predicate:\<close>\\
   803   @{text "P"}\\
   798   \<open>P\<close>\\
   804   @{text "Prems1 from the rule:"}\\
   799   \<open>Prems1 from the rule:\<close>\\
   805   @{text "R ?y x \<Longrightarrow> \<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P ?y"}\\
   800   \<open>R ?y x \<Longrightarrow> \<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P ?y\<close>\\
   806   @{text "Prems2 from the predicate:"}\\
   801   \<open>Prems2 from the predicate:\<close>\\
   807   @{term "\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x"}\\
   802   @{term "\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x"}\\
   808   \end{isabelle}
   803   \end{isabelle}
   809 
   804 
   810   and after application of the introduction rule 
   805   and after application of the introduction rule 
   811   using @{ML apply_prem_tac}, we are in the goal state
   806   using @{ML apply_prem_tac}, we are in the goal state
   812 
   807 
   813   \begin{isabelle}
   808   \begin{isabelle}
   814   @{text "1."}~@{term "\<And>y. R y x \<Longrightarrow> P y"}
   809   \<open>1.\<close>~@{term "\<And>y. R y x \<Longrightarrow> P y"}
   815   \end{isabelle}
   810   \end{isabelle}
   816   
   811   
   817   
   812   
   818 *}(*<*)oops(*>*)
   813 \<close>(*<*)oops(*>*)
   819 
   814 
   820 text {*
   815 text \<open>
   821   In order to make progress, we have to use the precondition
   816   In order to make progress, we have to use the precondition
   822   @{text "R y x"} (in general there can be many of them). The best way
   817   \<open>R y x\<close> (in general there can be many of them). The best way
   823   to get a handle on these preconditions is to open up another subproof,
   818   to get a handle on these preconditions is to open up another subproof,
   824   since the preconditions will then be bound to @{text prems}. Therfore we
   819   since the preconditions will then be bound to \<open>prems\<close>. Therfore we
   825   modify the function @{ML prepare_prem} as follows
   820   modify the function @{ML prepare_prem} as follows
   826 *}
   821 \<close>
   827 
   822 
   828 ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem =  
   823 ML %linenosgray\<open>fun prepare_prem params2 prems2 ctxt prem =  
   829   SUBPROOF (fn {prems, ...} =>
   824   SUBPROOF (fn {prems, ...} =>
   830   let
   825   let
   831     val prem' = prems MRS prem
   826     val prem' = prems MRS prem
   832   in 
   827   in 
   833     resolve_tac ctxt [case Thm.prop_of prem' of
   828     resolve_tac ctxt [case Thm.prop_of prem' of
   834            _ $ (Const (@{const_name All}, _) $ _) =>
   829            _ $ (Const (@{const_name All}, _) $ _) =>
   835                  prem' |> all_elims params2 
   830                  prem' |> all_elims params2 
   836                        |> imp_elims prems2
   831                        |> imp_elims prems2
   837          | _ => prem'] 1
   832          | _ => prem'] 1
   838   end) ctxt *}
   833   end) ctxt\<close>
   839 
   834 
   840 text {*
   835 text \<open>
   841   In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve 
   836   In Line 4 we use the \<open>prems\<close> from the @{ML SUBPROOF} and resolve 
   842   them with @{text prem}. In the simple cases, that is where the @{text prem} 
   837   them with \<open>prem\<close>. In the simple cases, that is where the \<open>prem\<close> 
   843   comes from a non-recursive premise of the rule, @{text prems} will be 
   838   comes from a non-recursive premise of the rule, \<open>prems\<close> will be 
   844   just the empty list and the function @{ML_ind MRS in Drule} does nothing. Similarly, in the 
   839   just the empty list and the function @{ML_ind MRS in Drule} does nothing. Similarly, in the 
   845   cases where the recursive premises of the rule do not have preconditions. 
   840   cases where the recursive premises of the rule do not have preconditions. 
   846   In case there are preconditions, then Line 4 discharges them. After
   841   In case there are preconditions, then Line 4 discharges them. After
   847   that we can proceed as before, i.e., check whether the outermost
   842   that we can proceed as before, i.e., check whether the outermost
   848   connective is @{text "\<forall>"}.
   843   connective is \<open>\<forall>\<close>.
   849   
   844   
   850   The function @{ML prove_intro_tac} only needs to be changed so that it
   845   The function @{ML prove_intro_tac} only needs to be changed so that it
   851   gives the context to @{ML prepare_prem} (Line 8). The modified version
   846   gives the context to @{ML prepare_prem} (Line 8). The modified version
   852   is below.
   847   is below.
   853 *}
   848 \<close>
   854 
   849 
   855 ML %linenosgray{*fun prove_intro_tac i preds rules =
   850 ML %linenosgray\<open>fun prove_intro_tac i preds rules =
   856   SUBPROOF (fn {params, prems, context, ...} =>
   851   SUBPROOF (fn {params, prems, context, ...} =>
   857   let
   852   let
   858     val cparams = map snd params
   853     val cparams = map snd params
   859     val (params1, params2) = chop (length cparams - length preds) cparams
   854     val (params1, params2) = chop (length cparams - length preds) cparams
   860     val (prems1, prems2) = chop (length prems - length rules) prems
   855     val (prems1, prems2) = chop (length prems - length rules) prems
   861   in
   856   in
   862     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   857     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   863     THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
   858     THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
   864   end) *}
   859   end)\<close>
   865 
   860 
   866 text {*
   861 text \<open>
   867   With these two functions we can now also prove the introduction
   862   With these two functions we can now also prove the introduction
   868   rule for the accessible part. 
   863   rule for the accessible part. 
   869 *}
   864 \<close>
   870 
   865 
   871 lemma accpartI:
   866 lemma accpartI:
   872 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   867 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   873 apply(tactic {* expand_tac @{context} @{thms accpart_def} *})
   868 apply(tactic \<open>expand_tac @{context} @{thms accpart_def}\<close>)
   874 apply(tactic {* prove_intro_tac 0 [acc_pred] acc_rules @{context} 1 *})
   869 apply(tactic \<open>prove_intro_tac 0 [acc_pred] acc_rules @{context} 1\<close>)
   875 done
   870 done
   876 
   871 
   877 text {*
   872 text \<open>
   878   Finally we need two functions that string everything together. The first
   873   Finally we need two functions that string everything together. The first
   879   function is the tactic that performs the proofs.
   874   function is the tactic that performs the proofs.
   880 *}
   875 \<close>
   881 
   876 
   882 ML %linenosgray{*fun intro_tac defs rules preds i ctxt =
   877 ML %linenosgray\<open>fun intro_tac defs rules preds i ctxt =
   883   EVERY1 [Object_Logic.rulify_tac ctxt,
   878   EVERY1 [Object_Logic.rulify_tac ctxt,
   884           rewrite_goal_tac ctxt defs,
   879           rewrite_goal_tac ctxt defs,
   885           REPEAT o (resolve_tac ctxt [@{thm allI}, @{thm impI}]),
   880           REPEAT o (resolve_tac ctxt [@{thm allI}, @{thm impI}]),
   886           prove_intro_tac i preds rules ctxt]*}
   881           prove_intro_tac i preds rules ctxt]\<close>
   887 
   882 
   888 text {*
   883 text \<open>
   889   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   884   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   890   Some testcases for this tactic are:
   885   Some testcases for this tactic are:
   891 *}
   886 \<close>
   892 
   887 
   893 lemma even0_intro:
   888 lemma even0_intro:
   894 shows "even 0"
   889 shows "even 0"
   895 by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *})
   890 by (tactic \<open>intro_tac eo_defs eo_rules eo_preds 0 @{context}\<close>)
   896 
   891 
   897 lemma evenS_intro:
   892 lemma evenS_intro:
   898 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   893 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   899 by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *})
   894 by (tactic \<open>intro_tac eo_defs eo_rules eo_preds 1 @{context}\<close>)
   900 
   895 
   901 lemma fresh_App:
   896 lemma fresh_App:
   902 shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
   897 shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
   903 by (tactic {* 
   898 by (tactic \<open>
   904   intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *})
   899   intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context}\<close>)
   905 
   900 
   906 text {*
   901 text \<open>
   907   The second function sets up in Line 4 the goals to be proved (this is easy
   902   The second function sets up in Line 4 the goals to be proved (this is easy
   908   for the introduction rules since they are exactly the rules 
   903   for the introduction rules since they are exactly the rules 
   909   given by the user) and iterates @{ML intro_tac} over all 
   904   given by the user) and iterates @{ML intro_tac} over all 
   910   introduction rules.
   905   introduction rules.
   911 *}
   906 \<close>
   912 
   907 
   913 ML %linenosgray{*fun intros rules preds defs lthy = 
   908 ML %linenosgray\<open>fun intros rules preds defs lthy = 
   914 let
   909 let
   915   fun intros_aux (i, goal) =
   910   fun intros_aux (i, goal) =
   916     Goal.prove lthy [] [] goal
   911     Goal.prove lthy [] [] goal
   917       (fn {context, ...} => intro_tac defs rules preds i context)
   912       (fn {context, ...} => intro_tac defs rules preds i context)
   918 in
   913 in
   919   map_index intros_aux rules
   914   map_index intros_aux rules
   920 end*}
   915 end\<close>
   921 
   916 
   922 text {*
   917 text \<open>
   923   The iteration is done with the function @{ML_ind map_index in Library} since we
   918   The iteration is done with the function @{ML_ind map_index in Library} since we
   924   need the introduction rule together with its number (counted from
   919   need the introduction rule together with its number (counted from
   925   @{text 0}). This completes the code for the functions deriving the
   920   \<open>0\<close>). This completes the code for the functions deriving the
   926   reasoning infrastructure. It remains to implement some administrative
   921   reasoning infrastructure. It remains to implement some administrative
   927   code that strings everything together.
   922   code that strings everything together.
   928 *}
   923 \<close>
   929 
   924 
   930 subsection {* Administrative Functions *}
   925 subsection \<open>Administrative Functions\<close>
   931 
   926 
   932 text {* 
   927 text \<open>
   933   We have produced various theorems (definitions, induction principles and
   928   We have produced various theorems (definitions, induction principles and
   934   introduction rules), but apart from the definitions, we have not yet 
   929   introduction rules), but apart from the definitions, we have not yet 
   935   registered them with the theorem database. This is what the functions 
   930   registered them with the theorem database. This is what the functions 
   936   @{ML_ind  note in Local_Theory} does. 
   931   @{ML_ind  note in Local_Theory} does. 
   937 
   932 
   938 
   933 
   939   For convenience, we use the following 
   934   For convenience, we use the following 
   940   three wrappers this function:
   935   three wrappers this function:
   941 *}
   936 \<close>
   942 
   937 
   943 ML %grayML{*fun note_many qname ((name, attrs), thms) = 
   938 ML %grayML\<open>fun note_many qname ((name, attrs), thms) = 
   944   Local_Theory.note ((Binding.qualify false qname name, attrs), thms) 
   939   Local_Theory.note ((Binding.qualify false qname name, attrs), thms) 
   945 
   940 
   946 fun note_single1 qname ((name, attrs), thm) = 
   941 fun note_single1 qname ((name, attrs), thm) = 
   947   note_many qname ((name, attrs), [thm]) 
   942   note_many qname ((name, attrs), [thm]) 
   948 
   943 
   949 fun note_single2 name attrs (qname, thm) = 
   944 fun note_single2 name attrs (qname, thm) = 
   950   note_many (Binding.name_of qname) ((name, attrs), [thm]) *}
   945   note_many (Binding.name_of qname) ((name, attrs), [thm])\<close>
   951 
   946 
   952 text {*
   947 text \<open>
   953   The function that ``holds everything together'' is @{text "add_inductive"}. 
   948   The function that ``holds everything together'' is \<open>add_inductive\<close>. 
   954   Its arguments are the specification of the predicates @{text "pred_specs"} 
   949   Its arguments are the specification of the predicates \<open>pred_specs\<close> 
   955   and the introduction rules @{text "rule_spec"}.   
   950   and the introduction rules \<open>rule_spec\<close>.   
   956 *}
   951 \<close>
   957 
   952 
   958 ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy =
   953 ML %linenosgray\<open>fun add_inductive pred_specs rule_specs lthy =
   959 let
   954 let
   960   val mxs = map snd pred_specs
   955   val mxs = map snd pred_specs
   961   val pred_specs' = map fst pred_specs
   956   val pred_specs' = map fst pred_specs
   962   val prednames = map fst pred_specs'
   957   val prednames = map fst pred_specs'
   963   val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs'
   958   val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs'
   979               [Attrib.internal (K (Rule_Cases.case_names case_names)),
   974               [Attrib.internal (K (Rule_Cases.case_names case_names)),
   980                Attrib.internal (K (Rule_Cases.consumes 1)),
   975                Attrib.internal (K (Rule_Cases.consumes 1)),
   981                Attrib.internal (K (Induct.induct_pred ""))]) 
   976                Attrib.internal (K (Induct.induct_pred ""))]) 
   982              (prednames ~~ ind_prins) 
   977              (prednames ~~ ind_prins) 
   983         |> snd
   978         |> snd
   984 end*}
   979 end\<close>
   985 
   980 
   986 text {*
   981 text \<open>
   987   In Line 3 the function extracts the syntax annotations from the predicates. 
   982   In Line 3 the function extracts the syntax annotations from the predicates. 
   988   Lines 4 to 6 extract the names of the predicates and generate
   983   Lines 4 to 6 extract the names of the predicates and generate
   989   the variables terms (with types) corresponding to the predicates. 
   984   the variables terms (with types) corresponding to the predicates. 
   990   Line 7 produces the argument types for each predicate. 
   985   Line 7 produces the argument types for each predicate. 
   991 
   986 
   992   Line 9 extracts the introduction rules from the specifications
   987   Line 9 extracts the introduction rules from the specifications
   993   and stores also in @{text namesattrs} the names and attributes the
   988   and stores also in \<open>namesattrs\<close> the names and attributes the
   994   user may have attached to these rules.
   989   user may have attached to these rules.
   995 
   990 
   996   Line 11 produces the definitions and also registers the definitions
   991   Line 11 produces the definitions and also registers the definitions
   997   in the local theory @{text "lthy'"}. The next two lines produce
   992   in the local theory \<open>lthy'\<close>. The next two lines produce
   998   the induction principles and the introduction rules (all of them
   993   the induction principles and the introduction rules (all of them
   999   as theorems). Both need the local theory @{text lthy'} in which
   994   as theorems). Both need the local theory \<open>lthy'\<close> in which
  1000   the definitions have been registered.
   995   the definitions have been registered.
  1001 
   996 
  1002   Lines 15 produces the name that is used to register the introduction
   997   Lines 15 produces the name that is used to register the introduction
  1003   rules. It is costum to collect all introduction rules under 
   998   rules. It is costum to collect all introduction rules under 
  1004   @{text "string.intros"}, whereby @{text "string"} stands for the 
   999   \<open>string.intros\<close>, whereby \<open>string\<close> stands for the 
  1005   @{text [quotes] "_"}-separated list of predicate names (for example
  1000   @{text [quotes] "_"}-separated list of predicate names (for example
  1006   @{text "even_odd"}. Also by custom, the case names in intuction 
  1001   \<open>even_odd\<close>. Also by custom, the case names in intuction 
  1007   proofs correspond to the names of the introduction rules. These
  1002   proofs correspond to the names of the introduction rules. These
  1008   are generated in Line 16.
  1003   are generated in Line 16.
  1009 
  1004 
  1010   Lines 18 and 19 now add to @{text "lthy'"} all the introduction rules 
  1005   Lines 18 and 19 now add to \<open>lthy'\<close> all the introduction rules 
  1011   und induction principles under the name @{text "mut_name.intros"} and
  1006   und induction principles under the name \<open>mut_name.intros\<close> and
  1012   @{text "mut_name.inducts"}, respectively (see previous paragraph).
  1007   \<open>mut_name.inducts\<close>, respectively (see previous paragraph).
  1013   
  1008   
  1014   Line 20 add further every introduction rule under its own name
  1009   Line 20 add further every introduction rule under its own name
  1015   (given by the user).\footnote{FIXME: what happens if the user did not give
  1010   (given by the user).\footnote{FIXME: what happens if the user did not give
  1016   any name.} Line 21 registers the induction principles. For this we have
  1011   any name.} Line 21 registers the induction principles. For this we have
  1017   to use some specific attributes. The first @{ML_ind  case_names in Rule_Cases} 
  1012   to use some specific attributes. The first @{ML_ind  case_names in Rule_Cases} 
  1022 
  1017 
  1023   This completes all the code and fits in with the ``front end'' described
  1018   This completes all the code and fits in with the ``front end'' described
  1024   in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}. 
  1019   in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}. 
  1025   Why the mut-name? 
  1020   Why the mut-name? 
  1026   What does @{ML Binding.qualify} do?}
  1021   What does @{ML Binding.qualify} do?}
  1027 *}
  1022 \<close>
  1028 (*<*)end(*>*)
  1023 (*<*)end(*>*)