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. In Line 4, @{ML [index] internalK in Thm} is a flag |
38 definition has been made. In Line 4, @{ML [index] internalK in Thm} is a flag |
39 attached to the theorem (others possibile flags are @{ML [index] definitionK in Thm} |
39 attached to the theorem (other possibile flags are @{ML [index] definitionK in Thm} |
40 and @{ML [index] axiomK in Thm}). These flags just classify theorems and have no |
40 and @{ML [index] axiomK in Thm}). These flags just classify theorems and have no |
41 significant meaning, except for tools that, for example, find theorems in |
41 significant meaning, except for tools that, for example, find theorems in |
42 the theorem database.\footnote{FIXME: put in the section about theorems.} We |
42 the theorem database.\footnote{FIXME: put in the section about theorems.} We |
43 also use @{ML [index] empty_binding in Attrib} in Line 3, since the definitions for |
43 also use @{ML [index] empty_binding in Attrib} in Line 3, since the definitions for |
44 our inductive predicates are not meant to be seen by the user and therefore |
44 our inductive predicates are not meant to be seen by the user and therefore |
111 Line 13 we quantify over all predicates; and in line 14 we just abstract |
111 Line 13 we quantify over all predicates; and in line 14 we just abstract |
112 over all the @{text "zs"}, i.e., the fresh arguments of the |
112 over all the @{text "zs"}, i.e., the fresh arguments of the |
113 predicate. A testcase for this function is |
113 predicate. A testcase for this function is |
114 *} |
114 *} |
115 |
115 |
116 local_setup %gray{* fn lthy => |
116 local_setup %gray {* fn lthy => |
117 let |
117 let |
118 val def = defn_aux lthy eo_orules eo_preds (e_pred, e_arg_tys) |
118 val def = defn_aux lthy eo_orules eo_preds (e_pred, e_arg_tys) |
119 in |
119 in |
120 writeln (Syntax.string_of_term lthy def); lthy |
120 writeln (Syntax.string_of_term lthy def); lthy |
121 end *} |
121 end *} |
167 text {* |
171 text {* |
168 The user will state the introduction rules using meta-implications and |
172 The user will state the introduction rules using meta-implications and |
169 meta-quanti\-fications. In Line 4, we transform these introduction rules |
173 meta-quanti\-fications. In Line 4, we transform these introduction rules |
170 into the object logic (since definitions cannot be stated with |
174 into the object logic (since definitions cannot be stated with |
171 meta-connectives). To do this transformation we have to obtain the theory |
175 meta-connectives). To do this transformation we have to obtain the theory |
172 behind the local theory (Line 3); with this theory we can use the function |
176 behind the local theory using the function @{ML [index] theory_of in ProofContext} |
|
177 (Line 3); with this theory we can use the function |
173 @{ML [index] atomize_term in ObjectLogic} to make the transformation (Line 4). The call |
178 @{ML [index] atomize_term in ObjectLogic} to make the transformation (Line 4). The call |
174 to @{ML defn_aux} in Line 5 produces all right-hand sides of the |
179 to @{ML defn_aux} in Line 5 produces all right-hand sides of the |
175 definitions. The actual definitions are then made in Line 7. The result of |
180 definitions. The actual definitions are then made in Line 7. The result of |
176 the function is a list of theorems and a local theory (the theorems are |
181 the function is a list of theorems and a local theory (the theorems are |
177 registered with the local theory). A testcase for this function is |
182 registered with the local theory). A testcase for this function is |
185 writeln (string_of_thms_no_vars lthy' defs); lthy |
190 writeln (string_of_thms_no_vars lthy' defs); lthy |
186 end *} |
191 end *} |
187 |
192 |
188 text {* |
193 text {* |
189 where we feed into the function all parameters corresponding to |
194 where we feed into the function all parameters corresponding to |
190 the @{text even}-@{text odd} example. The definitions we obtain |
195 the @{text even}/@{text odd} example. The definitions we obtain |
191 are: |
196 are: |
192 |
197 |
193 @{text [display, break] |
198 @{text [display, break] |
194 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
199 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
195 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
200 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
197 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
202 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
198 |
203 |
199 Note that in the testcase we return the local theory @{text lthy} |
204 Note that in the testcase we return the local theory @{text lthy} |
200 (not the modified @{text lthy'}). As a result the test case has no effect |
205 (not the modified @{text lthy'}). As a result the test case has no effect |
201 on the ambient theory. The reason is that if we introduce the |
206 on the ambient theory. The reason is that if we introduce the |
202 definition again, we pollute the name space with two versions of @{text "even"} |
207 definition again, we pollute the name space with two versions of |
203 and @{text "odd"}. |
208 @{text "even"} and @{text "odd"}. We want to avoid this here. |
204 |
209 |
205 This completes the code for introducing the definitions. Next we deal with |
210 This completes the code for introducing the definitions. Next we deal with |
206 the induction principles. |
211 the induction principles. |
207 *} |
212 *} |
208 |
213 |
232 The tactic will use the following helper function for instantiating universal |
237 The tactic will use the following helper function for instantiating universal |
233 quantifiers. |
238 quantifiers. |
234 *} |
239 *} |
235 |
240 |
236 ML{*fun inst_spec ctrm = |
241 ML{*fun inst_spec ctrm = |
237 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
242 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
238 |
243 |
239 text {* |
244 text {* |
240 This helper function instantiates the @{text "?x"} in the theorem |
245 This helper function instantiates the @{text "?x"} in the theorem |
241 @{thm spec} with a given @{ML_type cterm}. We call this helper function |
246 @{thm spec} with a given @{ML_type cterm}. We call this helper function |
242 in the following tactic, called @{text inst_spec_tac}\label{fun:instspectac}. |
247 in the following tactic.\label{fun:instspectac}. |
243 *} |
248 *} |
244 |
249 |
245 ML{*fun inst_spec_tac ctrms = |
250 ML{*fun inst_spec_tac ctrms = |
246 EVERY' (map (dtac o inst_spec) ctrms)*} |
251 EVERY' (map (dtac o inst_spec) ctrms)*} |
247 |
252 |
276 assume_tac]*} |
281 assume_tac]*} |
277 |
282 |
278 text {* |
283 text {* |
279 We have to give it as arguments the definitions, the premise (a list of |
284 We have to give it as arguments the definitions, the premise (a list of |
280 formulae) and the instantiations. The premise is @{text "even n"} in lemma |
285 formulae) and the instantiations. The premise is @{text "even n"} in lemma |
281 @{thm [source] manual_ind_prin_even}; in our code it will always be a list |
286 @{thm [source] manual_ind_prin_even} shown above; in our code it will always be a list |
282 consisting of a single formula. Compare this tactic with the manual proof |
287 consisting of a single formula. Compare this tactic with the manual proof |
283 for the lemma @{thm [source] manual_ind_prin_even}: as you can see there is |
288 for the lemma @{thm [source] manual_ind_prin_even}: as you can see there is |
284 almost a one-to-one correspondence between the \isacommand{apply}-script and |
289 almost a one-to-one correspondence between the \isacommand{apply}-script and |
285 the @{ML ind_tac}. Two testcases for this tactic are: |
290 the @{ML ind_tac}. We first rewrite the goal to use only object connectives (Line 2), |
|
291 "cut in" the premise (Line 3), unfold the definitions (Line 4), instantiate |
|
292 the assumptions of the goal (Line 5) and then conclude with @{ML assume_tac}. |
|
293 |
|
294 Two testcases for this tactic are: |
286 *} |
295 *} |
287 |
296 |
288 lemma automatic_ind_prin_even: |
297 lemma automatic_ind_prin_even: |
289 assumes prem: "even z" |
298 assumes prem: "even z" |
290 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z" |
299 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z" |
368 case that no introduction rules are given, the conclusion of this |
377 case that no introduction rules are given, the conclusion of this |
369 implication needs to be wrapped inside a @{term Trueprop}, otherwise |
378 implication needs to be wrapped inside a @{term Trueprop}, otherwise |
370 the Isabelle's goal mechanism will fail.\footnote{FIXME: check with |
379 the Isabelle's goal mechanism will fail.\footnote{FIXME: check with |
371 Stefan...is this so?} |
380 Stefan...is this so?} |
372 |
381 |
373 In Line 11 we set up the goal to be proved; in the next line we call the |
382 In Line 11 we set up the goal to be proved using the function @{ML [index] |
374 tactic for proving the induction principle. As mentioned before, this tactic |
383 prove in Goal}; in the next line we call the tactic for proving the |
375 expects the definitions, the premise and the (certified) predicates with |
384 induction principle. As mentioned before, this tactic expects the |
376 which the introduction rules have been substituted. The code in these two |
385 definitions, the premise and the (certified) predicates with which the |
377 lines will return a theorem. However, it is a theorem |
386 introduction rules have been substituted. The code in these two lines will |
378 proved inside the local theory @{text "lthy'"}, where the variables @{text |
387 return a theorem. However, it is a theorem proved inside the local theory |
379 "zs"} are free, but fixed (see Line 4). By exporting this theorem from @{text |
388 @{text "lthy'"}, where the variables @{text "zs"} are free, but fixed (see |
380 "lthy'"} (which contains the @{text "zs"} as free variables) to @{text |
389 Line 4). By exporting this theorem from @{text "lthy'"} (which contains the |
381 "lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}. |
390 @{text "zs"} as free variables) to @{text "lthy"} (which does not), we |
382 A testcase for this function is |
391 obtain the desired schematic variables @{text "?zs"}. A testcase for this |
383 *} |
392 function is |
384 |
393 *} |
385 local_setup %gray{* fn lthy => |
394 |
|
395 local_setup %gray {* fn lthy => |
386 let |
396 let |
387 val newpreds = [@{term "P::nat\<Rightarrow>bool"}, @{term "Q::nat\<Rightarrow>bool"}] |
397 val newpreds = [@{term "P::nat \<Rightarrow> bool"}, @{term "Q::nat \<Rightarrow> bool"}] |
388 val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
398 val cnewpreds = [@{cterm "P::nat \<Rightarrow> bool"}, @{cterm "Q::nat \<Rightarrow> bool"}] |
389 val newpred = @{term "P::nat\<Rightarrow>bool"} |
399 val newpred = @{term "P::nat \<Rightarrow> bool"} |
390 val srules = map (subst_free (eo_preds ~~ newpreds)) eo_rules |
400 val srules = map (subst_free (eo_preds ~~ newpreds)) eo_rules |
391 val intro = |
401 val intro = |
392 prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys) |
402 prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys) |
393 in |
403 in |
394 writeln (string_of_thm lthy intro); lthy |
404 writeln (string_of_thm lthy intro); lthy |
527 Similarly, the function @{ML imp_elims} eliminates preconditions from implications. |
537 Similarly, the function @{ML imp_elims} eliminates preconditions from implications. |
528 For example we can eliminate the preconditions @{text "A"} and @{text "B"} from |
538 For example we can eliminate the preconditions @{text "A"} and @{text "B"} from |
529 @{thm [source] imp_elims_test}: |
539 @{thm [source] imp_elims_test}: |
530 |
540 |
531 @{ML_response_fake [display, gray] |
541 @{ML_response_fake [display, gray] |
532 "writeln (string_of_thm_no_vars @{context} |
542 "let |
533 (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))" |
543 val res = imp_elims @{thms imp_elims_test'} @{thm imp_elims_test} |
|
544 in |
|
545 writeln (string_of_thm_no_vars @{context} res) |
|
546 end" |
534 "C"} |
547 "C"} |
535 |
548 |
536 Now we set up the proof for the introduction rule as follows: |
549 Now we set up the proof for the introduction rule as follows: |
537 *} |
550 *} |
538 |
551 |
579 differently. In the code below we will therefore separate them into @{text |
593 differently. In the code below we will therefore separate them into @{text |
580 "params1"} and @{text params2}, respectively @{text "prems1"} and @{text |
594 "params1"} and @{text params2}, respectively @{text "prems1"} and @{text |
581 "prems2"}. To do this separation, it is best to open a subproof with the |
595 "prems2"}. To do this separation, it is best to open a subproof with the |
582 tactic @{ML [index] SUBPROOF}, since this tactic provides us with the parameters (as |
596 tactic @{ML [index] SUBPROOF}, since this tactic provides us with the parameters (as |
583 list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s). |
597 list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s). |
584 The problem we have to overcome with @{ML SUBPROOF} |
598 The problem with @{ML SUBPROOF}, however, is that it always expects us to |
585 is, however, that this tactic always expects us to completely discharge the |
599 completely discharge the goal (see Section~\ref{sec:simpletacs}). This is |
586 goal (see Section~\ref{sec:simpletacs}). This is inconvenient for our |
600 a bit inconvenient for our gradual explanation of the proof here. Therefore |
587 gradual explanation of the proof here. To circumvent this inconvenience we |
601 we use first the function @{ML [index] FOCUS}, which does same as @{ML SUBPROOF} |
588 use the following modified tactic: |
602 but does not require us to completely discharge the goal. |
589 *} |
603 *} |
590 (*<*)oops(*>*) |
604 (*<*)oops(*>*) |
591 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*} |
|
592 |
|
593 text {* |
|
594 If the tactic inside @{ML SUBPROOF} fails, then the overall tactic will |
|
595 still succeed. With this testing tactic, we can gradually implement |
|
596 all necessary proof steps inside a subproof. Once we are finished, we |
|
597 just have to replace it with @{ML SUBPROOF}. |
|
598 *} |
|
599 |
|
600 text_raw {* |
605 text_raw {* |
601 \begin{figure}[t] |
606 \begin{figure}[t] |
602 \begin{minipage}{\textwidth} |
607 \begin{minipage}{\textwidth} |
603 \begin{isabelle} |
608 \begin{isabelle} |
604 *} |
609 *} |
623 |
628 |
624 text {* |
629 text {* |
625 First we calculate the values for @{text "params1/2"} and @{text "prems1/2"} |
630 First we calculate the values for @{text "params1/2"} and @{text "prems1/2"} |
626 from @{text "params"} and @{text "prems"}, respectively. To better see what is |
631 from @{text "params"} and @{text "prems"}, respectively. To better see what is |
627 going in our example, we will print out these values using the printing |
632 going in our example, we will print out these values using the printing |
628 function in Figure~\ref{fig:chopprint}. Since the tactic @{ML SUBPROOF} will |
633 function in Figure~\ref{fig:chopprint}. Since @{ML FOCUS} will |
629 supply us the @{text "params"} and @{text "prems"} as lists, we can |
634 supply us the @{text "params"} and @{text "prems"} as lists, we can |
630 separate them using the function @{ML [index] chop}. |
635 separate them using the function @{ML [index] chop}. |
631 *} |
636 *} |
632 |
637 |
633 ML{*fun chop_test_tac preds rules = |
638 ML %linenosgray{*fun chop_test_tac preds rules = |
634 SUBPROOF_test (fn {params, prems, context, ...} => |
639 FOCUS (fn {params, prems, context, ...} => |
635 let |
640 let |
636 val (params1, params2) = chop (length params - length preds) (map snd params) |
641 val cparams = map snd params |
|
642 val (params1, params2) = chop (length cparams - length preds) cparams |
637 val (prems1, prems2) = chop (length prems - length rules) prems |
643 val (prems1, prems2) = chop (length prems - length rules) prems |
638 in |
644 in |
639 chop_print params1 params2 prems1 prems2 context; no_tac |
645 chop_print params1 params2 prems1 prems2 context; all_tac |
640 end) *} |
646 end) *} |
641 |
647 |
642 text {* |
648 text {* |
643 For the separation we can rely on the fact that Isabelle deterministically |
649 For the separation we can rely on the fact that Isabelle deterministically |
644 produces parameters and premises in a goal state. The last parameters |
650 produces parameters and premises in a goal state. The last parameters |
645 that were introduced come from the quantifications in the definitions |
651 that were introduced come from the quantifications in the definitions |
646 (see the tactic @{ML expand_tac}). |
652 (see the tactic @{ML expand_tac}). |
647 Therefore we only have to subtract the number of predicates (in this |
653 Therefore we only have to subtract in Line 5 the number of predicates (in this |
648 case only @{text "1"}) from the lenghts of all parameters. Similarly |
654 case only @{text "1"}) from the lenghts of all parameters. Similarly |
649 with the @{text "prems"}: the last premises in the goal state come from |
655 with the @{text "prems"} in line 6: the last premises in the goal state come from |
650 unfolding the definition of the predicate in the conclusion. So we can |
656 unfolding the definition of the predicate in the conclusion. So we can |
651 just subtract the number of rules from the number of all premises. |
657 just subtract the number of rules from the number of all premises. |
652 Applying this tactic in our example |
658 To check our calculations we print them out in Line 8 using the |
|
659 function @{ML chop_print} from Figure~\ref{fig:chopprint} and then |
|
660 just do nothing, that is @{ML all_tac}. Applying this tactic in our example |
653 *} |
661 *} |
654 |
662 |
655 (*<*) |
663 (*<*) |
656 lemma fresh_Lam: |
664 lemma fresh_Lam: |
657 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
665 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
658 apply(tactic {* expand_tac @{thms fresh_def} *}) |
666 apply(tactic {* expand_tac @{thms fresh_def} *}) |
659 (*>*) |
667 (*>*) |
660 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} *}) |
668 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} 1 *}) |
661 (*<*)oops(*>*) |
669 (*<*)oops(*>*) |
662 |
670 |
663 text {* |
671 text {* |
664 gives |
672 gives |
665 |
673 |
689 |
697 |
690 @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"} |
698 @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"} |
691 |
699 |
692 To use this premise with @{ML rtac}, we need to instantiate its |
700 To use this premise with @{ML rtac}, we need to instantiate its |
693 quantifiers (with @{text params1}) and transform it into rule |
701 quantifiers (with @{text params1}) and transform it into rule |
694 format (using @{ML [index] rulify in ObjectLogic}. So we can modify the |
702 format (using @{ML [index] rulify in ObjectLogic}). So we can modify the |
695 subproof as follows: |
703 code as follows: |
696 *} |
704 *} |
697 |
705 |
698 ML %linenosgray{*fun apply_prem_tac i preds rules = |
706 ML %linenosgray{*fun apply_prem_tac i preds rules = |
699 SUBPROOF_test (fn {params, prems, context, ...} => |
707 FOCUS (fn {params, prems, context, ...} => |
700 let |
708 let |
701 val (params1, params2) = chop (length params - length preds) (map snd params) |
709 val cparams = map snd params |
|
710 val (params1, params2) = chop (length cparams - length preds) cparams |
702 val (prems1, prems2) = chop (length prems - length rules) prems |
711 val (prems1, prems2) = chop (length prems - length rules) prems |
703 in |
712 in |
704 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
713 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
705 THEN print_tac "" |
|
706 THEN no_tac |
|
707 end) *} |
714 end) *} |
708 |
715 |
709 text {* |
716 text {* |
710 The argument @{text i} corresponds to the number of the |
717 The argument @{text i} corresponds to the number of the |
711 introduction we want to prove. We will later on let it range |
718 introduction we want to prove. We will later on let it range |
717 (*<*) |
724 (*<*) |
718 lemma fresh_Lam: |
725 lemma fresh_Lam: |
719 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
726 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
720 apply(tactic {* expand_tac @{thms fresh_def} *}) |
727 apply(tactic {* expand_tac @{thms fresh_def} *}) |
721 (*>*) |
728 (*>*) |
722 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *}) |
729 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
723 (*<*)oops(*>*) |
730 (*<*)oops(*>*) |
724 |
731 |
725 text {* |
732 text {* |
726 Since we print out the goal state just after the application of |
733 The goal state we obtain is: |
727 @{ML rtac} (Line 8), we can see the goal state we obtain: |
|
728 |
734 |
729 \begin{isabelle} |
735 \begin{isabelle} |
730 @{text "1."}~@{prop "a \<noteq> b"}\\ |
736 @{text "1."}~@{text "\<dots> \<Longrightarrow> "}~@{prop "a \<noteq> b"}\\ |
731 @{text "2."}~@{prop "fresh a t"} |
737 @{text "2."}~@{text "\<dots> \<Longrightarrow> "}~@{prop "fresh a t"} |
732 \end{isabelle} |
738 \end{isabelle} |
733 |
739 |
734 As expected there are two subgoals, where the first comes from the |
740 As expected there are two subgoals, where the first comes from the |
735 non-recursive premise of the introduction rule and the second comes |
741 non-recursive premise of the introduction rule and the second comes |
736 from the recursive one. The first goal can be solved immediately |
742 from the recursive one. The first goal can be solved immediately |
771 *} |
777 *} |
772 |
778 |
773 ML{*fun prove_intro_tac i preds rules = |
779 ML{*fun prove_intro_tac i preds rules = |
774 SUBPROOF (fn {params, prems, ...} => |
780 SUBPROOF (fn {params, prems, ...} => |
775 let |
781 let |
776 val (params1, params2) = chop (length params - length preds) (map snd params) |
782 val cparams = map snd params |
|
783 val (params1, params2) = chop (length cparams - length preds) cparams |
777 val (prems1, prems2) = chop (length prems - length rules) prems |
784 val (prems1, prems2) = chop (length prems - length rules) prems |
778 in |
785 in |
779 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
786 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
780 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
787 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
781 end) *} |
788 end) *} |
782 |
789 |
783 text {* |
790 text {* |
784 Note that the tactic is now @{ML SUBPROOF}, not @{ML SUBPROOF_test}. |
791 Note that the tactic is now @{ML SUBPROOF}, not @{ML FOCUS} anymore. |
785 The full proof of the introduction rule is as follows: |
792 The full proof of the introduction rule is as follows: |
786 *} |
793 *} |
787 |
794 |
788 lemma fresh_Lam: |
795 lemma fresh_Lam: |
789 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
796 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
790 apply(tactic {* expand_tac @{thms fresh_def} *}) |
797 apply(tactic {* expand_tac @{thms fresh_def} *}) |
791 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
798 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
792 done |
799 done |
793 |
800 |
794 text {* |
801 text {* |
795 Phew! ...Unfortunately, not everything is done yet. If you look closely |
802 Phew!\ldots |
|
803 |
|
804 Unfortunately, not everything is done yet. If you look closely |
796 at the general principle outlined for the introduction rules in |
805 at the general principle outlined for the introduction rules in |
797 Section~\ref{sec:nutshell}, we have not yet dealt with the case where |
806 Section~\ref{sec:nutshell}, we have not yet dealt with the case where |
798 recursive premises have preconditions. The introduction rule |
807 recursive premises have preconditions. The introduction rule |
799 of the accessible part is such a rule. |
808 of the accessible part is such a rule. |
800 *} |
809 *} |
801 |
810 |
802 lemma accpartI: |
811 lemma accpartI: |
803 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x" |
812 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x" |
804 apply(tactic {* expand_tac @{thms accpart_def} *}) |
813 apply(tactic {* expand_tac @{thms accpart_def} *}) |
805 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} *}) |
814 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} 1 *}) |
806 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} *}) |
815 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} 1 *}) |
807 |
816 |
808 txt {* |
817 txt {* |
809 Here @{ML chop_test_tac} prints out the following |
818 Here @{ML chop_test_tac} prints out the following |
810 values for @{text "params1/2"} and @{text "prems1/2"} |
819 values for @{text "params1/2"} and @{text "prems1/2"} |
811 |
820 |
866 *} |
875 *} |
867 |
876 |
868 ML %linenosgray{*fun prove_intro_tac i preds rules = |
877 ML %linenosgray{*fun prove_intro_tac i preds rules = |
869 SUBPROOF (fn {params, prems, context, ...} => |
878 SUBPROOF (fn {params, prems, context, ...} => |
870 let |
879 let |
871 val (params1, params2) = chop (length params - length preds) (map snd params) |
880 val cparams = map snd params |
|
881 val (params1, params2) = chop (length cparams - length preds) cparams |
872 val (prems1, prems2) = chop (length prems - length rules) prems |
882 val (prems1, prems2) = chop (length prems - length rules) prems |
873 in |
883 in |
874 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
884 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
875 THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1) |
885 THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1) |
876 end) *} |
886 end) *} |
950 |
960 |
951 For convenience, we use the following |
961 For convenience, we use the following |
952 three wrappers this function: |
962 three wrappers this function: |
953 *} |
963 *} |
954 |
964 |
955 ML{*fun reg_many qname ((name, attrs), thms) = |
965 ML{*fun note_many qname ((name, attrs), thms) = |
956 LocalTheory.note Thm.theoremK |
966 LocalTheory.note Thm.theoremK |
957 ((Binding.qualify false qname name, attrs), thms) |
967 ((Binding.qualify false qname name, attrs), thms) |
958 |
968 |
959 fun reg_single1 qname ((name, attrs), thm) = |
969 fun note_single1 qname ((name, attrs), thm) = |
960 reg_many qname ((name, attrs), [thm]) |
970 note_many qname ((name, attrs), [thm]) |
961 |
971 |
962 fun reg_single2 name attrs (qname, thm) = |
972 fun note_single2 name attrs (qname, thm) = |
963 reg_many (Binding.name_of qname) ((name, attrs), [thm]) *} |
973 note_many (Binding.name_of qname) ((name, attrs), [thm]) *} |
964 |
974 |
965 text {* |
975 text {* |
966 The function that ``holds everything together'' is @{text "add_inductive"}. |
976 The function that ``holds everything together'' is @{text "add_inductive"}. |
967 Its arguments are the specification of the predicates @{text "pred_specs"} |
977 Its arguments are the specification of the predicates @{text "pred_specs"} |
968 and the introduction rules @{text "rule_spec"}. |
978 and the introduction rules @{text "rule_spec"}. |
983 val intro_rules = intros rules preds defs lthy' |
993 val intro_rules = intros rules preds defs lthy' |
984 |
994 |
985 val mut_name = space_implode "_" (map Binding.name_of prednames) |
995 val mut_name = space_implode "_" (map Binding.name_of prednames) |
986 val case_names = map (Binding.name_of o fst) namesattrs |
996 val case_names = map (Binding.name_of o fst) namesattrs |
987 in |
997 in |
988 lthy' |> reg_many mut_name ((@{binding "intros"}, []), intro_rules) |
998 lthy' |> note_many mut_name ((@{binding "intros"}, []), intro_rules) |
989 ||>> reg_many mut_name ((@{binding "inducts"}, []), ind_prins) |
999 ||>> note_many mut_name ((@{binding "inducts"}, []), ind_prins) |
990 ||>> fold_map (reg_single1 mut_name) (namesattrs ~~ intro_rules) |
1000 ||>> fold_map (note_single1 mut_name) (namesattrs ~~ intro_rules) |
991 ||>> fold_map (reg_single2 @{binding "induct"} |
1001 ||>> fold_map (note_single2 @{binding "induct"} |
992 [Attrib.internal (K (RuleCases.case_names case_names)), |
1002 [Attrib.internal (K (RuleCases.case_names case_names)), |
993 Attrib.internal (K (RuleCases.consumes 1)), |
1003 Attrib.internal (K (RuleCases.consumes 1)), |
994 Attrib.internal (K (Induct.induct_pred ""))]) |
1004 Attrib.internal (K (Induct.induct_pred ""))]) |
995 (prednames ~~ ind_prins) |
1005 (prednames ~~ ind_prins) |
996 |> snd |
1006 |> snd |