CookBook/Package/Ind_Code.thy
changeset 183 8bb4eaa2ec92
parent 180 9c25418db6f0
child 184 c7f04a008c9c
equal deleted inserted replaced
182:4d0e2edd476d 183:8bb4eaa2ec92
     1 theory Ind_Code
     1 theory Ind_Code
     2 imports "../Base" "../FirstSteps" Simple_Inductive_Package Ind_Prelims
     2 imports "../Base" "../FirstSteps" Simple_Inductive_Package Ind_Prelims
     3 begin
     3 begin
     4 
     4 
     5 section {* Code *}
     5 section {* Code *}
     6 
       
     7 subsection {* Definitions *}
       
     8 
     6 
     9 text {*
     7 text {*
    10   @{text [display] "rule ::= \<And>xs. As \<Longrightarrow> (\<And>ys. Bs \<Longrightarrow> pred ss)\<^isup>* \<Longrightarrow> pred ts"}
     8   @{text [display] "rule ::= \<And>xs. As \<Longrightarrow> (\<And>ys. Bs \<Longrightarrow> pred ss)\<^isup>* \<Longrightarrow> pred ts"}
    11 
     9 
    12   @{text [display] "orule ::= \<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>* \<longrightarrow> pred ts"}
    10   @{text [display] "orule ::= \<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>* \<longrightarrow> pred ts"}
    40 text {*
    38 text {*
    41   First we have to produce for each predicate its definitions of the form
    39   First we have to produce for each predicate its definitions of the form
    42 
    40 
    43   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    41   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    44 
    42 
    45   We use the following wrapper function to make the definition via
    43   In order to make definitions, we use the following wrapper for 
    46   @{ML LocalTheory.define}. The function takes a predicate name, a syntax
    44   @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax
    47   annotation and a term representing the right-hand side of the definition.
    45   annotation and a term representing the right-hand side of the definition.
    48 *}
    46 *}
    49 
    47 
    50 ML %linenosgray{*fun make_defs ((predname, syn), trm) lthy =
    48 ML %linenosgray{*fun make_defs ((predname, syn), trm) lthy =
    51 let 
    49 let 
    54 in 
    52 in 
    55   (thm, lthy') 
    53   (thm, lthy') 
    56 end*}
    54 end*}
    57 
    55 
    58 text {*
    56 text {*
    59   It returns the definition (as theorem) and the local theory in which this definition has 
    57   It returns the definition (as a theorem) and the local theory in which this definition has 
    60   been made. In Line 4 @{ML internalK in Thm} is just a flag attached to the 
    58   been made. In Line 4 @{ML internalK in Thm} is just a flag attached to the 
    61   theorem (others possibilities are @{ML definitionK in Thm} or @{ML axiomK in Thm}). 
    59   theorem (others possibilities are @{ML definitionK in Thm} and @{ML axiomK in Thm}). 
    62   These flags just classify theorems and have no significant meaning, except 
    60   These flags just classify theorems and have no significant meaning, except 
    63   for tools such as finding theorems in the theorem database. We also
    61   for tools that, for example, find theorems in the theorem database. We also
    64   use @{ML empty_binding in Attrib} in Line 3, since the definition does 
    62   use @{ML empty_binding in Attrib} in Line 3, since the definition does 
    65   not need any theorem attributes. Note the definition has not yet been 
    63   not need to have any theorem attributes. A testcase for this function is
    66   stored in the theorem database. So at the moment we can only refer to it
       
    67   via the return value. A testcase for this functions is
       
    68 *}
    64 *}
    69 
    65 
    70 local_setup %gray {* fn lthy =>
    66 local_setup %gray {* fn lthy =>
    71 let
    67 let
    72   val arg =  ((Binding.name "MyTrue", NoSyn), @{term True})
    68   val arg =  ((Binding.name "MyTrue", NoSyn), @{term True})
    74 in
    70 in
    75   warning (str_of_thm lthy' def); lthy'
    71   warning (str_of_thm lthy' def); lthy'
    76 end *}
    72 end *}
    77 
    73 
    78 text {*
    74 text {*
    79   which prints out the theorem @{prop "MyTrue \<equiv> True"}. Since we are
    75   which makes the difinition @{prop "MyTrue \<equiv> True"} and then prints it out. 
    80   testing the function inside \isacommand{local\_setup} we have also
    76   Since we are testing the function inside \isacommand{local\_setup}, i.e.~make
    81   access to theorem associated with this definition.
    77   changes to the ambient theory, we can query the definition using the usual
       
    78   command \isacommand{thm}:
    82 
    79 
    83   \begin{isabelle}
    80   \begin{isabelle}
    84   \isacommand{thm}~@{text "MyTrue_def"}\\
    81   \isacommand{thm}~@{text "MyTrue_def"}\\
    85   @{text "> MyTrue \<equiv> True"}
    82   @{text "> MyTrue \<equiv> True"}
    86   \end{isabelle}
    83   \end{isabelle}
    87 
    84 
    88   The next function constructs the term for the definition, namely 
    85   The next two functions construct the terms we need for the definitions, namely 
       
    86   terms of the form 
    89 
    87 
    90   @{text [display] "\<lambda>\<^raw:$zs$>. \<forall>preds. orules \<longrightarrow> pred \<^raw:$zs$>"}
    88   @{text [display] "\<lambda>\<^raw:$zs$>. \<forall>preds. orules \<longrightarrow> pred \<^raw:$zs$>"}
    91 
    89 
    92   The variables @{text "\<^raw:$zs$>"} need to be chosen so to not occur
    90   The variables @{text "\<^raw:$zs$>"} need to be chosen so that they do not occur
    93   in the @{text orules} and also be distinct from @{text "pred"}. The function
    91   in the @{text orules} and also be distinct from @{text "preds"}. 
    94   constructs the term for one particular predicate @{text "pred"}; the number
    92 
    95   of @{text "\<^raw:$zs$>"} is determined by the nunber of types. 
    93   The first function constructs the term for one particular predicate @{text
       
    94   "pred"}; the number of arguments @{text "\<^raw:$zs$>"} of this predicate is
       
    95   determined by the number of argument types of @{text "arg_tys"}.
    96 *}
    96 *}
    97 
    97 
    98 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
    98 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
    99 let 
    99 let 
   100   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   100   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   110   |> fold_rev mk_all preds
   110   |> fold_rev mk_all preds
   111   |> fold_rev lambda fresh_args 
   111   |> fold_rev lambda fresh_args 
   112 end*}
   112 end*}
   113 
   113 
   114 text {*
   114 text {*
   115   The code in Lines 5 to 9 produce the fresh @{text "\<^raw:$zs$>"} with which the 
   115   The code in Lines 5 to 9 produce the fresh @{text "\<^raw:$zs$>"}. For this
   116   predicate is applied. For this it pairs every type with a string @{text [quotes] "z"} 
   116   it pairs every argument type with the string @{text [quotes] "z"} (Line 7);
   117   (Line 7); then generates variants for all these strings (names) so that they are 
   117   then generates variants for all these strings so that they are unique
   118   unique w.r.t.~to the orules and predicates; in Line 9 it generates the corresponding 
   118   w.r.t.~to the @{text "orules"} and the predicates; in Line 9 it generates the
   119   variable terms for the unique names.
   119   corresponding variable terms for the unique strings.
   120 
   120 
   121   The unique free variables are applied to the predicate (Line 11); then
   121   The unique free variables are applied to the predicate (Line 11) using the
   122   the @{text orules} are prefixed (Line 12); in Line 13 we
   122   function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in
   123   quantify over all predicates; and in line 14 we just abstract over all
   123   Line 13 we quantify over all predicates; and in line 14 we just abstract
   124   the (fresh)  @{text "\<^raw:$zs$>"}, i.e.~the arguments of the predicate.
   124   over all the @{text "\<^raw:$zs$>"}, i.e.~the fresh arguments of the
       
   125   predicate.
   125 
   126 
   126   A testcase for this function is
   127   A testcase for this function is
   127 *}
   128 *}
   128 
   129 
   129 local_setup %gray{* fn lthy =>
   130 local_setup %gray{* fn lthy =>
   138 in
   139 in
   139   warning (Syntax.string_of_term lthy def); lthy
   140   warning (Syntax.string_of_term lthy def); lthy
   140 end *}
   141 end *}
   141 
   142 
   142 text {*
   143 text {*
   143   It constructs the term for the predicate @{term "even"}. So we obtain as printout
   144   It constructs the left-hand side for the definition of @{term "even"}. So we obtain 
   144   the term
   145   as printout the term
   145 
   146 
   146   @{text [display] 
   147   @{text [display] 
   147 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   148 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   148                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   149                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   149 
   150 
   150   The main function for the definitions now has to just iterate
   151   The main function for the definitions now has to just iterate
   151   the function @{ML defs_aux} over all predicates. THis is what the
   152   the function @{ML defs_aux} over all predicates. 
   152   next function does. 
       
   153 *}
   153 *}
   154 
   154 
   155 ML %linenosgray{*fun definitions rules preds prednames syns arg_typss lthy =
   155 ML %linenosgray{*fun definitions rules preds prednames syns arg_typss lthy =
   156 let
   156 let
   157   val thy = ProofContext.theory_of lthy
   157   val thy = ProofContext.theory_of lthy
   160 in
   160 in
   161   fold_map make_defs (prednames ~~ syns ~~ defs) lthy
   161   fold_map make_defs (prednames ~~ syns ~~ defs) lthy
   162 end*}
   162 end*}
   163 
   163 
   164 text {*
   164 text {*
   165   The argument @{text "preds"} is the list of predicates as @{ML_type term}s;
   165   The argument @{text "preds"} is again the the list of predicates as 
       
   166   @{ML_type term}s;
   166   the argument @{text "prednames"} is the list of names of the predicates;
   167   the argument @{text "prednames"} is the list of names of the predicates;
   167   @{text "arg_tyss"} is the list of argument-type-lists. 
   168   @{text "arg_tyss"} is the list of argument-type-lists for each predicate. 
   168   
   169   
   169   In line 4 we generate the intro rules in the object logic; for this we have to 
   170   The user give the introduction rules using meta-implications and meta-quantifications.
   170   obtain the theory behind the local theory (Line 3); with this we can
   171   In line 4 we transform the introduction rules into the object logic (definitions
   171   call @{ML defs_aux} to generate the terms for the left-hand sides.
   172   cannot use them). To do the transformation we have to 
   172   The actual definitions are made in Line 7.
   173   obtain the theory behind the local theory (Line 3); with this theory 
       
   174   we can use the function @{ML ObjectLogic.atomize_term} to make the
       
   175   transformation (Line 4). The call to @{ML defs_aux} in Line 5 produces all
       
   176   left-hand sides of the definitions. The actual definitions are then made in Line 7.
       
   177   As the result we obtain a list of theorems and a local theory. 
   173 
   178 
   174   A testcase for this function is 
   179   A testcase for this function is 
   175 *}
   180 *}
   176 
   181 
   177 local_setup %gray {* fn lthy =>
   182 local_setup %gray {* fn lthy =>
   183   val prednames = [Binding.name "even", Binding.name "odd"] 
   188   val prednames = [Binding.name "even", Binding.name "odd"] 
   184   val syns = [NoSyn, NoSyn] 
   189   val syns = [NoSyn, NoSyn] 
   185   val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]]
   190   val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]]
   186   val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy
   191   val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy
   187 in
   192 in
   188   warning (str_of_thms lthy' defs); lthy
   193   warning (str_of_thms lthy' defs); lthy'
   189 end *}
   194 end *}
   190 
   195 
   191 text {*
   196 text {*
   192 
   197 
   193   It prints out the two definitions
   198   \begin{isabelle}
   194 
   199   \isacommand{thm}~@{text "even_def odd_def"}\\
   195   @{text [display] 
   200   @{text [break]
   196 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   201 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   197                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, 
   202 >                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   198  odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   203 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   199                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   204 >                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
       
   205   \end{isabelle}
       
   206 
   200 
   207 
   201   This completes the code concerning the definitions. Next comes the code for
   208   This completes the code concerning the definitions. Next comes the code for
   202   the induction principles. 
   209   the induction principles. 
   203 
   210 
   204   Recall the proof for the induction principle for @{term "even"}: 
   211   Let us now turn to the induction principles. Recall that the proof of the 
       
   212   induction principle for @{term "even"} was:
   205 *}
   213 *}
   206 
   214 
   207 lemma 
   215 lemma 
   208   assumes prems: "even n"
   216 assumes prems: "even n"
   209   shows "P 0 \<Longrightarrow> 
   217 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   210              (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
       
   211 apply(atomize (full))
   218 apply(atomize (full))
   212 apply(cut_tac prems)
   219 apply(cut_tac prems)
   213 apply(unfold even_def)
   220 apply(unfold even_def)
   214 apply(drule spec[where x=P])
   221 apply(drule spec[where x=P])
   215 apply(drule spec[where x=Q])
   222 apply(drule spec[where x=Q])
   216 apply(assumption)
   223 apply(assumption)
   217 done
   224 done
   218 
   225 
   219 text {* 
   226 text {* 
   220   To automate this proof we need to be able to instantiate universal 
   227   We have to implement code that constructs the induction principle and then
   221   quantifiers. For this we use the following helper function. It
   228   a tactic that automatically proves it. 
   222   instantiates the @{text "?x"} in @{thm spec} with a @{ML_type cterm}.
   229   
       
   230   The tactic will use the following helper function for instantiating universal 
       
   231   quantifiers. This function instantiates the @{text "?x"} in the theorem 
       
   232   @{thm spec} with a given @{ML_type cterm}.
   223 *}
   233 *}
   224 
   234 
   225 ML{*fun inst_spec ctrm = 
   235 ML{*fun inst_spec ctrm = 
   226  Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
   236  Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
   227 
   237 
   228 text {*
   238 text {*
   229   For example we can use it to instantiate an assumption:
   239   For example we can use it in the following proof to instantiate the 
   230 *}
   240   three quantifiers in the assumption. We use the tactic
       
   241 *}
       
   242 
       
   243 ML{*fun inst_spec_tac ctrms = 
       
   244   EVERY' (map (dtac o inst_spec) ctrms)*}
       
   245 
       
   246 text {*
       
   247   and then apply use it with the @{ML_type cterm}s @{text "y1\<dots>y3"}. 
       
   248   *}
   231 
   249 
   232 lemma "\<forall>(x1::nat) (x2::nat) (x3::nat). P x1 x2 x3 \<Longrightarrow> True"
   250 lemma "\<forall>(x1::nat) (x2::nat) (x3::nat). P x1 x2 x3 \<Longrightarrow> True"
   233 apply (tactic {* 
   251 apply (tactic {* 
   234   let 
   252   inst_spec_tac  [@{cterm "y1::nat"},@{cterm "y2::nat"},@{cterm "y3::nat"}] 1 *})
   235     val ctrms = [@{cterm "y1::nat"},@{cterm "y2::nat"},@{cterm "y3::nat"}]
       
   236   in 
       
   237     EVERY1 (map (dtac o inst_spec) ctrms)
       
   238   end *})
       
   239 txt {* 
   253 txt {* 
   240   where it produces the goal state
   254   We obtain the goal state
   241 
   255 
   242   \begin{minipage}{\textwidth}
   256   \begin{minipage}{\textwidth}
   243   @{subgoals} 
   257   @{subgoals} 
   244   \end{minipage}*}
   258   \end{minipage}*}
   245 (*<*)oops(*>*)
   259 (*<*)oops(*>*)
   246 
   260 
   247 text {*
   261 text {*
   248   Now the tactic for proving the induction rules can be implemented 
   262   Now the complete tactic for proving the induction principles can 
   249   as follows
   263   be implemented as follows:
   250 *}
   264 *}
   251 
   265 
   252 ML %linenosgray{*fun induction_tac defs prems insts =
   266 ML %linenosgray{*fun induction_tac defs prems insts =
   253   EVERY1 [ObjectLogic.full_atomize_tac,
   267   EVERY1 [ObjectLogic.full_atomize_tac,
   254           cut_facts_tac prems,
   268           cut_facts_tac prems,
   255           K (rewrite_goals_tac defs),
   269           K (rewrite_goals_tac defs),
   256           EVERY' (map (dtac o inst_spec) insts),
   270           inst_spec_tac insts,
   257           assume_tac]*}
   271           assume_tac]*}
   258 
   272 
   259 text {*
   273 text {*
   260   We only have to give it as arguments the premises and the instantiations.
   274   We only have to give it as arguments the premises and the instantiations.
   261   A testcase for the tactic is
   275   A testcase for the tactic is
   262 *}
   276 *}
   263 
   277 
       
   278 ML{*fun test_tac prems = 
       
   279 let
       
   280   val defs = [@{thm even_def}, @{thm odd_def}]
       
   281   val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
       
   282 in 
       
   283   induction_tac defs prems insts 
       
   284 end*}
       
   285 
       
   286 text {*
       
   287   which indeed proves the induction principle. 
       
   288 *}
       
   289 
   264 lemma 
   290 lemma 
   265   assumes prems: "even n"
   291 assumes prems: "even n"
   266   shows "P 0 \<Longrightarrow> 
   292 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   267            (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   293 apply(tactic {* test_tac @{thms prems} *})
   268 apply(tactic {* 
       
   269   let
       
   270      val defs = [@{thm even_def}, @{thm odd_def}]
       
   271      val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
       
   272   in 
       
   273     induction_tac defs @{thms prems} insts 
       
   274   end *})
       
   275 done
   294 done
   276 
   295 
   277 
   296 text {*
   278 text {*
       
   279   which indeed proves the lemma. 
       
   280 
       
   281   While the generic proof for the induction principle is relatively simple, 
   297   While the generic proof for the induction principle is relatively simple, 
   282   it is a bit harder to set up the goals just from the given introduction 
   298   it is a bit harder to construct the goals from just the introduction 
   283   rules. For this we have to construct for each predicate @{text "pred"}
   299   rules the user states. In general we have to construct for each predicate 
       
   300   @{text "pred"} a goal of the form
   284 
   301 
   285   @{text [display] 
   302   @{text [display] 
   286   "\<And>\<^raw:$zs$>. pred \<^raw:$zs$> \<Longrightarrow> rules[preds := \<^raw:$Ps$>] \<Longrightarrow> \<^raw:$P$>\<^raw:$zs$>"}
   303   "\<And>\<^raw:$zs$>. pred \<^raw:$zs$> \<Longrightarrow> rules[preds := \<^raw:$Ps$>] \<Longrightarrow> \<^raw:$P$>\<^raw:$zs$>"}
   287 
   304 
   288   where the given predicates @{text preds} are replaced by new distinct 
   305   where the given predicates @{text preds} are replaced in the introduction 
   289   ones written as @{text "\<^raw:$Ps$>"}, and also need to be applied to
   306   rule @{text "rules"} by new distinct variables written as @{text "\<^raw:$Ps$>"}. 
   290   new variables @{text "\<^raw:$zs$>"}. 
   307   We also need to generate fresh arguments for the predicate @{text "pred"} and
       
   308   the @{text "\<^raw:$P$>"} in the conclusion of the induction principle.
   291 
   309 
   292   The function below expects that the rules are already appropriately
   310   The function below expects that the rules are already appropriately
   293   replaced. The argument @{text "mrules"} stands for these modified
   311   substitued. The argument @{text "srules"} stands for these substituted
   294   introduction rules; @{text cnewpreds} are the certified terms coresponding
   312   introduction rules; @{text cnewpreds} are the certified terms coresponding
   295   to the variables @{text "\<^raw:$Ps$>"}; @{text "pred"} is the predicate for
   313   to the variables @{text "\<^raw:$Ps$>"}; @{text "pred"} is the predicate for
   296   which we prove the introduction principle; @{text "newpred"} is its
   314   which we prove the introduction principle; @{text "newpred"} is its
   297   replacement and @{text "tys"} are the types of its argument.
   315   replacement and @{text "tys"} are the argument types of this predicate.
   298 *}
   316 *}
   299 
   317 
   300 ML %linenosgray{* fun prove_induction lthy defs mrules cnewpreds ((pred, newpred), tys)  =
   318 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), tys)  =
   301 let
   319 let
   302   val zs = replicate (length tys) "z"
   320   val zs = replicate (length tys) "z"
   303   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   321   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   304   val newargs = map Free (newargnames ~~ tys)
   322   val newargs = map Free (newargnames ~~ tys)
   305   
   323   
   306   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   324   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   307   val goal = Logic.list_implies 
   325   val goal = Logic.list_implies 
   308          (mrules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   326          (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   309 in
   327 in
   310   Goal.prove lthy' [] [prem] goal
   328   Goal.prove lthy' [] [prem] goal
   311   (fn {prems, ...} => induction_tac defs prems cnewpreds)
   329   (fn {prems, ...} => induction_tac defs prems cnewpreds)
   312   |> singleton (ProofContext.export lthy' lthy)
   330   |> singleton (ProofContext.export lthy' lthy)
   313 end *}
   331 end *}
   314 
   332 
   315 text {* 
   333 text {* 
   316   In Line 3 we produce a list of names @{text "\<^raw:$zs$>"} according to the type 
   334   In Line 3 we produce a name @{text "\<^raw:$zs$>"} for each type in the 
   317   list. Line 4 makes these names unique and declare them as \emph{free} (but fixed)
   335   argument type list. Line 4 makes these names unique and declares them as 
   318   variables. These variables are free in the new theory @{text "lthy'"}. In Line 5
   336   \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In 
   319   we just construct the terms corresponding to the variables. The term variables are
   337   Line 5 we just construct the terms corresponding to these variables. 
   320   applied to the predicate in Line 7 (this is the first premise 
   338   The term variables are applied to the predicate in Line 7 (this corresponds
   321   @{text "pred \<^raw:$zs$>"} of the induction principle). In Line 8 and 9
   339   to the first premise @{text "pred \<^raw:$zs$>"} of the induction principle). 
   322   we first the term  @{text "\<^raw:$P$>\<^raw:$zs$>"} and then add
   340   In Line 8 and 9, we first construct the term  @{text "\<^raw:$P$>\<^raw:$zs$>"} 
   323   the (modified) introduction rules as premises.
   341   and then add the (modified) introduction rules as premises. In case that
   324 
   342   no introduction rules are given, the conclusion of this implications needs
   325   In Line 11 we set up the goal to be proved; call the induction tactic in
   343   to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal
   326   Line 13. This returns a theorem. However, it is a theorem proved inside
   344   mechanism will fail. 
   327   the local theory @{text "lthy'"} where the variables @{text "\<^raw:$zs$>"} are
   345 
   328   fixed, but free. By exporting this theorem from @{text "lthy'"} (which does contain
   346   In Line 11 we set up the goal to be proved; then call the tactic for proving the 
   329   the  @{text "\<^raw:$zs$>"} as free) to @{text "lthy"} (which does not), we
   347   induction principle. This tactic expects the (certified) predicates with which
   330   obtain the desired quantifications @{text "\<And>\<^raw:$zs$>"}.
   348   the introduction rules have been substituted. This will return a theorem. 
   331 
   349   However, it is a theorem proved inside the local theory @{text "lthy'"} where 
   332   So it is left to produce the modified rules and 
   350   the variables @{text "\<^raw:$zs$>"} are fixed, but free. By exporting this 
   333 *}
   351   theorem from @{text "lthy'"} (which contains the  @{text "\<^raw:$zs$>"} 
   334 
   352   as free) to @{text "lthy"} (which does not), we obtain the desired quantifications 
   335 ML %linenosgray{*fun inductions rules defs preds tyss lthy1  =
   353   @{text "\<And>\<^raw:$zs$>"}.
       
   354 
       
   355   Now it is left to produce the new predicated with which the introduction
       
   356   rules are substituted. 
       
   357 *}
       
   358 
       
   359 ML %linenosgray{*fun inductions rules defs preds tyss lthy  =
   336 let
   360 let
   337   val Ps = replicate (length preds) "P"
   361   val Ps = replicate (length preds) "P"
   338   val (newprednames, lthy2) = Variable.variant_fixes Ps lthy1
   362   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   339   
   363   
   340   val thy = ProofContext.theory_of lthy2
   364   val thy = ProofContext.theory_of lthy'
   341 
   365 
   342   val tyss' = map (fn tys => tys ---> HOLogic.boolT) tyss
   366   val tyss' = map (fn tys => tys ---> HOLogic.boolT) tyss
   343   val newpreds = map Free (newprednames ~~ tyss')
   367   val newpreds = map Free (newprednames ~~ tyss')
   344   val cnewpreds = map (cterm_of thy) newpreds
   368   val cnewpreds = map (cterm_of thy) newpreds
   345   val rules' = map (subst_free (preds ~~ newpreds)) rules
   369   val rules' = map (subst_free (preds ~~ newpreds)) rules
   346 
   370 
   347 in
   371 in
   348   map (prove_induction lthy2 defs rules' cnewpreds) 
   372   map (prove_induction lthy' defs rules' cnewpreds) 
   349         (preds ~~ newpreds ~~ tyss)
   373         (preds ~~ newpreds ~~ tyss)
   350           |> ProofContext.export lthy2 lthy1
   374           |> ProofContext.export lthy' lthy
   351 end*}
   375 end*}
   352 
   376 
   353 ML {*
   377 ML {*
   354   let 
   378   let 
   355     val rules = [@{prop "even (0::nat)"},
   379     val rules = [@{prop "even (0::nat)"},
   456            Attrib.internal (K (Induct.induct_pred ""))]), [([th], [])]))
   480            Attrib.internal (K (Induct.induct_pred ""))]), [([th], [])]))
   457           (pred_specs ~~ ind_rules)) #>> maps snd) 
   481           (pred_specs ~~ ind_rules)) #>> maps snd) 
   458     |> snd
   482     |> snd
   459 end*}
   483 end*}
   460 
   484 
   461 ML{*fun read_specification' vars specs lthy =
       
   462 let 
       
   463   val specs' = map (fn (a, s) => (a, [s])) specs
       
   464   val ((varst, specst), _) = 
       
   465                    Specification.read_specification vars specs' lthy
       
   466   val specst' = map (apsnd the_single) specst
       
   467 in   
       
   468   (varst, specst')
       
   469 end*}
       
   470 
       
   471 ML{*fun add_inductive pred_specs rule_specs lthy =
   485 ML{*fun add_inductive pred_specs rule_specs lthy =
   472 let
   486 let
   473   val (pred_specs', rule_specs') = 
   487   val ((pred_specs', rule_specs'), _) = 
   474     read_specification' pred_specs rule_specs lthy
   488          Specification.read_spec pred_specs rule_specs lthy
   475 in
   489 in
   476   add_inductive_i pred_specs' rule_specs' lthy
   490   add_inductive_i pred_specs' rule_specs' lthy
   477 end*} 
   491 end*} 
   478 
   492 
   479 ML{*val spec_parser = 
   493 ML{*val spec_parser =