660 \begin{readmore} |
660 \begin{readmore} |
661 The function @{ML SUBPROOF} is defined in @{ML_file "Pure/subgoal.ML"} and |
661 The function @{ML SUBPROOF} is defined in @{ML_file "Pure/subgoal.ML"} and |
662 also described in \isccite{sec:results}. |
662 also described in \isccite{sec:results}. |
663 \end{readmore} |
663 \end{readmore} |
664 |
664 |
665 A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. |
665 Similar but less powerful functions than @{ML SUBPROOF} are @{ML SUBGOAL} |
666 It allows you to inspect a given subgoal. With this you can implement |
666 and @{ML CSUBGOAL}. They allow you to inspect a given subgoal (the former |
667 a tactic that applies a rule according to the topmost logic connective in the |
667 presents the subgoal as a @{ML_type term}, while the latter as a @{ML_type |
668 subgoal (to illustrate this we only analyse a few connectives). The code |
668 cterm}). With this you can implement a tactic that applies a rule according |
669 of the tactic is as follows.\label{tac:selecttac} |
669 to the topmost logic connective in the subgoal (to illustrate this we only |
670 *} |
670 analyse a few connectives). The code of the tactic is as |
671 |
671 follows.\label{tac:selecttac} |
672 ML %linenosgray{*fun select_tac (t,i) = |
672 |
|
673 *} |
|
674 |
|
675 ML %linenosgray{*fun select_tac (t, i) = |
673 case t of |
676 case t of |
674 @{term "Trueprop"} $ t' => select_tac (t',i) |
677 @{term "Trueprop"} $ t' => select_tac (t', i) |
675 | @{term "op \<Longrightarrow>"} $ _ $ t' => select_tac (t',i) |
678 | @{term "op \<Longrightarrow>"} $ _ $ t' => select_tac (t', i) |
676 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
679 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
677 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
680 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
678 | @{term "Not"} $ _ => rtac @{thm notI} i |
681 | @{term "Not"} $ _ => rtac @{thm notI} i |
679 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
682 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
680 | _ => all_tac*} |
683 | _ => all_tac*} |
725 text {* |
728 text {* |
726 then we have to be careful to not apply the tactic to the two subgoals produced by |
729 then we have to be careful to not apply the tactic to the two subgoals produced by |
727 the first goal. To do this can result in quite messy code. In contrast, |
730 the first goal. To do this can result in quite messy code. In contrast, |
728 the ``reverse application'' is easy to implement. |
731 the ``reverse application'' is easy to implement. |
729 |
732 |
730 The tactic @{ML "CSUBGOAL"} is similar to @{ML SUBGOAL} except that it takes |
733 Of course, this example is |
731 a @{ML_type cterm} instead of a @{ML_type term}. Of course, this example is |
|
732 contrived: there are much simpler methods available in Isabelle for |
734 contrived: there are much simpler methods available in Isabelle for |
733 implementing a proof procedure analysing a goal according to its topmost |
735 implementing a proof procedure analysing a goal according to its topmost |
734 connective. These simpler methods use tactic combinators, which we will |
736 connective. These simpler methods use tactic combinators, which we will |
735 explain in the next section. |
737 explain in the next section. |
736 |
738 |
1456 end" |
1458 end" |
1457 "(True \<and> Q \<equiv> Q, P \<or> True \<and> Q \<equiv> P \<or> True \<and> Q)"} |
1459 "(True \<and> Q \<equiv> Q, P \<or> True \<and> Q \<equiv> P \<or> True \<and> Q)"} |
1458 |
1460 |
1459 Here the conversion of @{thm [source] true_conj1} only applies |
1461 Here the conversion of @{thm [source] true_conj1} only applies |
1460 in the first case, but fails in the second. The whole conversion |
1462 in the first case, but fails in the second. The whole conversion |
1461 does not fail, however, because the combinator @{ML else_conv} will then |
1463 does not fail, however, because the combinator @{ML Conv.else_conv} will then |
1462 try out @{ML Conv.all_conv}, which always succeeds. |
1464 try out @{ML Conv.all_conv}, which always succeeds. |
1463 |
1465 |
1464 Apart from the function @{ML beta_conversion in Thm}, which is able to fully |
1466 Apart from the function @{ML beta_conversion in Thm}, which is able to fully |
1465 beta-normalise a term, the conversions so far are restricted in that they |
1467 beta-normalise a term, the conversions so far are restricted in that they |
1466 only apply to the outer-most level of a @{ML_type cterm}. In what follows we |
1468 only apply to the outer-most level of a @{ML_type cterm}. In what follows we |
1598 let |
1600 let |
1599 val ctxt = ProofContext.init (Thm.theory_of_cterm goal) |
1601 val ctxt = ProofContext.init (Thm.theory_of_cterm goal) |
1600 in |
1602 in |
1601 CONVERSION |
1603 CONVERSION |
1602 (Conv.params_conv ~1 (fn ctxt => |
1604 (Conv.params_conv ~1 (fn ctxt => |
1603 (Conv.prems_conv ~1 (if_true1_conv ctxt)) then_conv |
1605 (Conv.prems_conv ~1 (if_true1_conv ctxt) then_conv |
1604 Conv.concl_conv ~1 (all_true1_conv ctxt)) ctxt) i |
1606 Conv.concl_conv ~1 (all_true1_conv ctxt))) ctxt) i |
1605 end)*} |
1607 end)*} |
1606 |
1608 |
1607 text {* |
1609 text {* |
1608 We call the conversions with the argument @{ML "~1"}. This is to |
1610 We call the conversions with the argument @{ML "~1"}. This is to |
1609 analyse all parameters, premises and conclusions. If we call them with |
1611 analyse all parameters, premises and conclusions. If we call them with |
1627 |
1629 |
1628 To sum up this section, conversions are not as powerful as the simplifier |
1630 To sum up this section, conversions are not as powerful as the simplifier |
1629 and simprocs; the advantage of conversions, however, is that you never have |
1631 and simprocs; the advantage of conversions, however, is that you never have |
1630 to worry about non-termination. |
1632 to worry about non-termination. |
1631 |
1633 |
|
1634 \begin{exercise}\label{ex:addconversion} |
|
1635 Write a tactic that is based on conversions which does the same as the simproc in |
|
1636 exercise \ref{ex:addsimproc}, that is replaces terms of the form @{term "t\<^isub>1 + t\<^isub>2"} |
|
1637 by their result. You can make the same assumptions as in \ref{ex:addsimproc}. |
|
1638 \end{exercise} |
|
1639 |
1632 \begin{readmore} |
1640 \begin{readmore} |
1633 See @{ML_file "Pure/conv.ML"} for more information about conversion combinators. |
1641 See @{ML_file "Pure/conv.ML"} for more information about conversion combinators. |
1634 Further conversions are defined in @{ML_file "Pure/thm.ML"}, |
1642 Further conversions are defined in @{ML_file "Pure/thm.ML"}, |
1635 @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}. |
1643 @{ML_file "Pure/drule.ML"} and @{ML_file "Pure/meta_simplifier.ML"}. |
1636 \end{readmore} |
1644 \end{readmore} |
1637 *} |
1645 |
|
1646 *} |
|
1647 |
1638 |
1648 |
1639 |
1649 |
1640 |
1650 |
1641 section {* Structured Proofs *} |
1651 section {* Structured Proofs *} |
1642 |
1652 |