ProgTutorial/Package/Ind_Code.thy
changeset 562 daf404920ab9
parent 552 82c482467d75
child 565 cecd7a941885
equal deleted inserted replaced
561:aec7073d4645 562:daf404920ab9
    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 *}
    27 
    27 
    28 ML %linenosgray{*fun make_defn ((predname, mx), trm) lthy =
    28 ML %linenosgray{*fun make_defn ((predname, mx), trm) lthy =
    29 let 
    29 let 
    30   val arg = ((predname, mx), (Attrib.empty_binding, 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*}
    35 
    35 
    36 text {*
    36 text {*
    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_binding in Attrib} 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:
   134   @{text "arg_tyss"} is the list of argument-type-lists.
   134   @{text "arg_tyss"} is the list of argument-type-lists.
   135 *}
   135 *}
   136 
   136 
   137 ML %linenosgray{*fun defns rules preds prednames mxs arg_typss lthy =
   137 ML %linenosgray{*fun defns rules preds prednames mxs arg_typss lthy =
   138 let
   138 let
   139   val thy = Proof_Context.theory_of lthy
   139   val orules = map (Object_Logic.atomize_term lthy) rules
   140   val orules = map (Object_Logic.atomize_term thy) rules
       
   141   val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) 
   140   val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) 
   142 in
   141 in
   143   fold_map make_defn (prednames ~~ mxs ~~ defs) lthy
   142   fold_map make_defn (prednames ~~ mxs ~~ defs) lthy
   144 end*}
   143 end*}
   145 
   144 
   213   quantifiers. 
   212   quantifiers. 
   214 *}
   213 *}
   215 
   214 
   216 ML %grayML{*fun inst_spec ctrm =
   215 ML %grayML{*fun inst_spec ctrm =
   217 let
   216 let
   218   val cty = ctyp_of_term ctrm
   217   val cty = Thm.ctyp_of_cterm ctrm
   219 in 
   218 in 
   220   Drule.instantiate' [SOME cty] [NONE, SOME ctrm] @{thm spec} 
   219   Thm.instantiate' [SOME cty] [NONE, SOME ctrm] @{thm spec} 
   221 end*}
   220 end*}
   222 
   221 
   223 text {*
   222 text {*
   224   This helper function uses the function @{ML_ind instantiate' in Drule}
   223   This helper function uses the function @{ML_ind instantiate' in Thm}
   225   and instantiates the @{text "?x"} in the theorem @{thm spec} with a given
   224   and instantiates the @{text "?x"} in the theorem @{thm spec} with a given
   226   @{ML_type cterm}. We call this helper function in the following
   225   @{ML_type cterm}. We call this helper function in the following
   227   tactic.\label{fun:instspectac}.
   226   tactic.\label{fun:instspectac}.
   228 *}
   227 *}
   229 
   228 
   230 ML %grayML{*fun inst_spec_tac ctrms = 
   229 ML %grayML{*fun inst_spec_tac ctxt ctrms = 
   231   EVERY' (map (dtac o inst_spec) ctrms)*}
   230   EVERY' (map (dresolve_tac ctxt o single o inst_spec) ctrms)*}
   232 
   231 
   233 text {*
   232 text {*
   234   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   233   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   235   proof below to instantiate the three quantifiers in the assumption. 
   234   proof below to instantiate the three quantifiers in the assumption. 
   236 *}
   235 *}
   237 
   236 
   238 lemma 
   237 lemma 
   239 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   238 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   240 shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   239 shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   241 apply (tactic {* 
   240 apply (tactic {* 
   242   inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
   241   inst_spec_tac @{context} [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
   243 txt {* 
   242 txt {* 
   244   We obtain the goal state
   243   We obtain the goal state
   245 
   244 
   246   \begin{minipage}{\textwidth}
   245   \begin{minipage}{\textwidth}
   247   @{subgoals} 
   246   @{subgoals} 
   255 
   254 
   256 ML %linenosgray{*fun ind_tac ctxt defs prem insts =
   255 ML %linenosgray{*fun ind_tac ctxt defs prem insts =
   257   EVERY1 [Object_Logic.full_atomize_tac ctxt,
   256   EVERY1 [Object_Logic.full_atomize_tac ctxt,
   258           cut_facts_tac prem,
   257           cut_facts_tac prem,
   259           rewrite_goal_tac ctxt defs,
   258           rewrite_goal_tac ctxt defs,
   260           inst_spec_tac insts,
   259           inst_spec_tac ctxt insts,
   261           assume_tac]*}
   260           assume_tac ctxt]*}
   262 
   261 
   263 text {*
   262 text {*
   264   We have to give it as arguments the definitions, the premise (a list of
   263   We have to give it as arguments the definitions, the premise (a list of
   265   formulae) and the instantiations. The premise is @{text "even n"} in lemma
   264   formulae) and the instantiations. The premise is @{text "even n"} in lemma
   266   @{thm [source] manual_ind_prin_even} shown above; in our code it will always be a list
   265   @{thm [source] manual_ind_prin_even} shown above; in our code it will always be a list
   403 ML %linenosgray{*fun inds rules defs preds arg_tyss lthy  =
   402 ML %linenosgray{*fun inds rules defs preds arg_tyss lthy  =
   404 let
   403 let
   405   val Ps = replicate (length preds) "P"
   404   val Ps = replicate (length preds) "P"
   406   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   405   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   407   
   406   
   408   val thy = Proof_Context.theory_of lthy'
       
   409 
       
   410   val tyss' = map (fn tys => tys ---> HOLogic.boolT) arg_tyss
   407   val tyss' = map (fn tys => tys ---> HOLogic.boolT) arg_tyss
   411   val newpreds = map Free (newprednames ~~ tyss')
   408   val newpreds = map Free (newprednames ~~ tyss')
   412   val cnewpreds = map (cterm_of thy) newpreds
   409   val cnewpreds = map (Thm.cterm_of lthy') newpreds
   413   val srules = map (subst_free (preds ~~ newpreds)) rules
   410   val srules = map (subst_free (preds ~~ newpreds)) rules
   414 
   411 
   415 in
   412 in
   416   map (prove_ind lthy' defs srules cnewpreds) 
   413   map (prove_ind lthy' defs srules cnewpreds) 
   417         (preds ~~ newpreds ~~ arg_tyss)
   414         (preds ~~ newpreds ~~ arg_tyss)
   420 
   417 
   421 text {*
   418 text {*
   422   In Line 3, we generate a string @{text [quotes] "P"} for each predicate. 
   419   In Line 3, we generate a string @{text [quotes] "P"} for each predicate. 
   423   In Line 4, we use the same trick as in the previous function, that is making the 
   420   In Line 4, we use the same trick as in the previous function, that is making the 
   424   @{text "Ps"} fresh and declaring them as free, but fixed, in
   421   @{text "Ps"} fresh and declaring them as free, but fixed, in
   425   the new local theory @{text "lthy'"}. From the local theory we extract
   422   the new local theory @{text "lthy'"}. In Line 6, we construct the types of these new predicates
   426   the ambient theory in Line 6. We need this theory in order to certify 
       
   427   the new predicates. In Line 8, we construct the types of these new predicates
       
   428   using the given argument types. Next we turn them into terms and subsequently
   423   using the given argument types. Next we turn them into terms and subsequently
   429   certify them (Line 9 and 10). We can now produce the substituted introduction rules 
   424   certify them (Line 7 and 8). We can now produce the substituted introduction rules 
   430   (Line 11) using the function @{ML_ind subst_free in Term}. Line 14 and 15 just iterate 
   425   (Line 9) using the function @{ML_ind subst_free in Term}. Line 12 and 13 just iterate 
   431   the proofs for all predicates.
   426   the proofs for all predicates.
   432   From this we obtain a list of theorems. Finally we need to export the 
   427   From this we obtain a list of theorems. Finally we need to export the 
   433   fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"} 
   428   fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"} 
   434   (Line 16).
   429   (Line 14).
   435 
   430 
   436   A testcase for this function is
   431   A testcase for this function is
   437 *}
   432 *}
   438 
   433 
   439 local_setup %gray {* fn lthy =>
   434 local_setup %gray {* fn lthy =>
   540 *}
   535 *}
   541 
   536 
   542 ML %linenosgray{*fun expand_tac ctxt defs =
   537 ML %linenosgray{*fun expand_tac ctxt defs =
   543   Object_Logic.rulify_tac ctxt 1
   538   Object_Logic.rulify_tac ctxt 1
   544   THEN rewrite_goal_tac ctxt defs 1
   539   THEN rewrite_goal_tac ctxt defs 1
   545   THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *}
   540   THEN (REPEAT (resolve_tac ctxt [@{thm allI}, @{thm impI}] 1)) *}
   546 
   541 
   547 text {*
   542 text {*
   548   The function in Line 2 ``rulifies'' the lemma.\footnote{FIXME: explain this better} 
   543   The function in Line 2 ``rulifies'' the lemma.\footnote{FIXME: explain this better} 
   549   This will turn out to 
   544   This will turn out to 
   550   be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
   545   be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
   677   We now have to select from @{text prems2} the premise 
   672   We now have to select from @{text prems2} the premise 
   678   that corresponds to the introduction rule we prove, namely:
   673   that corresponds to the introduction rule we prove, namely:
   679 
   674 
   680   @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"}
   675   @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"}
   681 
   676 
   682   To use this premise with @{ML rtac}, we need to instantiate its 
   677   To use this premise with @{ML resolve_tac}, we need to instantiate its 
   683   quantifiers (with @{text params1}) and transform it into rule 
   678   quantifiers (with @{text params1}) and transform it into rule 
   684   format (using @{ML_ind  rulify in Object_Logic}). So we can modify the 
   679   format (using @{ML_ind  rulify in Object_Logic}). So we can modify the 
   685   code as follows:
   680   code as follows:
   686 *}
   681 *}
   687 
   682 
   690   let
   685   let
   691     val cparams = map snd params
   686     val cparams = map snd params
   692     val (params1, params2) = chop (length cparams - length preds) cparams
   687     val (params1, params2) = chop (length cparams - length preds) cparams
   693     val (prems1, prems2) = chop (length prems - length rules) prems
   688     val (prems1, prems2) = chop (length prems - length rules) prems
   694   in
   689   in
   695     rtac (Object_Logic.rulify context (all_elims params1 (nth prems2 i))) 1
   690     resolve_tac  context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   696   end) *}
   691   end) *}
   697 
   692 
   698 text {* 
   693 text {* 
   699   The argument @{text i} corresponds to the number of the 
   694   The argument @{text i} corresponds to the number of the 
   700   introduction we want to prove. We will later on let it range
   695   introduction we want to prove. We will later on let it range
   742   The premise of the complicated case must have at least one  @{text "\<forall>"}
   737   The premise of the complicated case must have at least one  @{text "\<forall>"}
   743   coming from the quantification over the @{text preds}. So 
   738   coming from the quantification over the @{text preds}. So 
   744   we can implement the following function
   739   we can implement the following function
   745 *}
   740 *}
   746 
   741 
   747 ML %grayML{*fun prepare_prem params2 prems2 prem =  
   742 ML %grayML{*fun prepare_prem ctxt params2 prems2 prem =  
   748   rtac (case prop_of prem of
   743   resolve_tac ctxt [case Thm.prop_of prem of
   749            _ $ (Const (@{const_name All}, _) $ _) =>
   744            _ $ (Const (@{const_name All}, _) $ _) =>
   750                  prem |> all_elims params2 
   745                  prem |> all_elims params2 
   751                       |> imp_elims prems2
   746                       |> imp_elims prems2
   752          | _ => prem) *}
   747          | _ => prem] *}
   753 
   748 
   754 text {* 
   749 text {* 
   755   which either applies the premise outright (the default case) or if 
   750   which either applies the premise outright (the default case) or if 
   756   it has an outermost universial quantification, instantiates it first 
   751   it has an outermost universial quantification, instantiates it first 
   757   with  @{text "params1"} and then @{text "prems1"}. The following 
   752   with  @{text "params1"} and then @{text "prems1"}. The following 
   763   let
   758   let
   764     val cparams = map snd params
   759     val cparams = map snd params
   765     val (params1, params2) = chop (length cparams - length preds) cparams
   760     val (params1, params2) = chop (length cparams - length preds) cparams
   766     val (prems1, prems2) = chop (length prems - length rules) prems
   761     val (prems1, prems2) = chop (length prems - length rules) prems
   767   in
   762   in
   768     rtac (Object_Logic.rulify context (all_elims params1 (nth prems2 i))) 1
   763     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   769     THEN EVERY1 (map (prepare_prem params2 prems2) prems1)
   764     THEN EVERY1 (map (prepare_prem context params2 prems2) prems1)
   770   end) *}
   765   end) *}
   771 
   766 
   772 text {*
   767 text {*
   773   Note that the tactic is now @{ML SUBPROOF}, not @{ML FOCUS in Subgoal} anymore. 
   768   Note that the tactic is now @{ML SUBPROOF}, not @{ML FOCUS in Subgoal} anymore. 
   774   The full proof of the introduction rule is as follows:
   769   The full proof of the introduction rule is as follows:
   833 ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem =  
   828 ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem =  
   834   SUBPROOF (fn {prems, ...} =>
   829   SUBPROOF (fn {prems, ...} =>
   835   let
   830   let
   836     val prem' = prems MRS prem
   831     val prem' = prems MRS prem
   837   in 
   832   in 
   838     rtac (case prop_of prem' of
   833     resolve_tac ctxt [case Thm.prop_of prem' of
   839            _ $ (Const (@{const_name All}, _) $ _) =>
   834            _ $ (Const (@{const_name All}, _) $ _) =>
   840                  prem' |> all_elims params2 
   835                  prem' |> all_elims params2 
   841                        |> imp_elims prems2
   836                        |> imp_elims prems2
   842          | _ => prem') 1
   837          | _ => prem'] 1
   843   end) ctxt *}
   838   end) ctxt *}
   844 
   839 
   845 text {*
   840 text {*
   846   In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve 
   841   In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve 
   847   them with @{text prem}. In the simple cases, that is where the @{text prem} 
   842   them with @{text prem}. In the simple cases, that is where the @{text prem} 
   862   let
   857   let
   863     val cparams = map snd params
   858     val cparams = map snd params
   864     val (params1, params2) = chop (length cparams - length preds) cparams
   859     val (params1, params2) = chop (length cparams - length preds) cparams
   865     val (prems1, prems2) = chop (length prems - length rules) prems
   860     val (prems1, prems2) = chop (length prems - length rules) prems
   866   in
   861   in
   867     rtac (Object_Logic.rulify context (all_elims params1 (nth prems2 i))) 1
   862     resolve_tac context [Object_Logic.rulify context (all_elims params1 (nth prems2 i))] 1
   868     THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
   863     THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
   869   end) *}
   864   end) *}
   870 
   865 
   871 text {*
   866 text {*
   872   With these two functions we can now also prove the introduction
   867   With these two functions we can now also prove the introduction
   885 *}
   880 *}
   886 
   881 
   887 ML %linenosgray{*fun intro_tac defs rules preds i ctxt =
   882 ML %linenosgray{*fun intro_tac defs rules preds i ctxt =
   888   EVERY1 [Object_Logic.rulify_tac ctxt,
   883   EVERY1 [Object_Logic.rulify_tac ctxt,
   889           rewrite_goal_tac ctxt defs,
   884           rewrite_goal_tac ctxt defs,
   890           REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]),
   885           REPEAT o (resolve_tac ctxt [@{thm allI}, @{thm impI}]),
   891           prove_intro_tac i preds rules ctxt]*}
   886           prove_intro_tac i preds rules ctxt]*}
   892 
   887 
   893 text {*
   888 text {*
   894   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   889   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   895   Some testcases for this tactic are:
   890   Some testcases for this tactic are: