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: |