Mercurial > cpdt > repo
comparison src/Match.v @ 460:38549f152568
Proofreading pass through Chapter 14
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 29 Aug 2012 15:04:17 -0400 |
parents | 0650420c127b |
children | 4320c1a967c2 |
comparison
equal
deleted
inserted
replaced
459:9fbf3b4dac29 | 460:38549f152568 |
---|---|
144 end. | 144 end. |
145 (* begin thide *) | 145 (* begin thide *) |
146 Qed. | 146 Qed. |
147 (* end thide *) | 147 (* end thide *) |
148 | 148 |
149 (** The first case matches trivially, but its body tactic fails, since the conclusion does not begin with a quantifier or implication. In a similar ML match, that would mean that the whole pattern-match fails. In Coq, we backtrack and try the next pattern, which also matches. Its body tactic succeeds, so the overall tactic succeeds as well. | 149 (** The first case matches trivially, but its body tactic fails, since the conclusion does not begin with a quantifier or implication. In a similar ML match, the whole pattern-match would fail. In Coq, we backtrack and try the next pattern, which also matches. Its body tactic succeeds, so the overall tactic succeeds as well. |
150 | 150 |
151 The example shows how failure can move to a different pattern within a [match]. Failure can also trigger an attempt to find _a different way of matching a single pattern_. Consider another example: *) | 151 The example shows how failure can move to a different pattern within a [match]. Failure can also trigger an attempt to find _a different way of matching a single pattern_. Consider another example: *) |
152 | 152 |
153 Theorem m2 : forall P Q R : Prop, P -> Q -> R -> Q. | 153 Theorem m2 : forall P Q R : Prop, P -> Q -> R -> Q. |
154 intros; match goal with | 154 intros; match goal with |
510 Ltac inster n := | 510 Ltac inster n := |
511 intuition; | 511 intuition; |
512 match n with | 512 match n with |
513 | S ?n' => | 513 | S ?n' => |
514 match goal with | 514 match goal with |
515 | [ H : forall x : ?T, _, x : ?T |- _ ] => generalize (H x); inster n' | 515 | [ H : forall x : ?T, _, y : ?T |- _ ] => generalize (H y); inster n' |
516 end | 516 end |
517 end. | 517 end. |
518 (* end thide *) | 518 (* end thide *) |
519 | 519 |
520 (** The tactic begins by applying propositional simplification. Next, it checks if any chain length remains, failing if not. If so, it tries all possible ways of instantiating quantified hypotheses with properly typed local variables. It is critical to realize that, if the recursive call [inster n'] fails, then the [match goal] just seeks out another way of unifying its pattern against proof state. Thus, this small amount of code provides an elegant demonstration of how backtracking [match] enables exhaustive search. | 520 (** The tactic begins by applying propositional simplification. Next, it checks if any chain length remains, failing if not. If so, it tries all possible ways of instantiating quantified hypotheses with properly typed local variables. It is critical to realize that, if the recursive call [inster n'] fails, then the [match goal] just seeks out another way of unifying its pattern against proof state. Thus, this small amount of code provides an elegant demonstration of how backtracking [match] enables exhaustive search. |
618 | [ |- ?P /\ _ --> _ ] => search P | 618 | [ |- ?P /\ _ --> _ ] => search P |
619 | [ |- _ /\ ?P --> _ ] => apply comm_prem; search P | 619 | [ |- _ /\ ?P --> _ ] => apply comm_prem; search P |
620 | [ |- _ --> _ ] => progress (tac || (apply and_True_prem; tac)) | 620 | [ |- _ --> _ ] => progress (tac || (apply and_True_prem; tac)) |
621 end. | 621 end. |
622 | 622 |
623 (** To understand how [search_prem] works, we turn first to the final [match]. If the premise begins with a conjunction, we call the [search] procedure on each of the conjuncts, or only the first conjunct, if that already yields a case where [tac] does not fail. The call [search P] expects and maintains the invariant that the premise is of the form [P /\ Q] for some [Q]. We pass [P] explicitly as a kind of decreasing induction measure, to avoid looping forever when [tac] always fails. The second [match] case calls a commutativity lemma to realize this invariant, before passing control to [search]. The final [match] case tries applying [tac] directly and then, if that fails, changes the form of the goal by adding an extraneous [True] conjunct and calls [tac] again. | 623 (** To understand how [search_prem] works, we turn first to the final [match]. If the premise begins with a conjunction, we call the [search] procedure on each of the conjuncts, or only the first conjunct, if that already yields a case where [tac] does not fail. The call [search P] expects and maintains the invariant that the premise is of the form [P /\ Q] for some [Q]. We pass [P] explicitly as a kind of decreasing induction measure, to avoid looping forever when [tac] always fails. The second [match] case calls a commutativity lemma to realize this invariant, before passing control to [search]. The final [match] case tries applying [tac] directly and then, if that fails, changes the form of the goal by adding an extraneous [True] conjunct and calls [tac] again. The %\index{tactics!progress}%[progress] tactical fails when its argument tactic succeeds without changing the current subgoal. |
624 | 624 |
625 The [search] function itself tries the same tricks as in the last case of the final [match]. Additionally, if neither works, it checks if [P] is a conjunction. If so, it calls itself recursively on each conjunct, first applying associativity lemmas to maintain the goal-form invariant. | 625 The [search] function itself tries the same tricks as in the last case of the final [match]. Additionally, if neither works, it checks if [P] is a conjunction. If so, it calls itself recursively on each conjunct, first applying associativity lemmas to maintain the goal-form invariant. |
626 | 626 |
627 We will also want a dual function [search_conc], which does tree search through an [imp] conclusion. *) | 627 We will also want a dual function [search_conc], which does tree search through an [imp] conclusion. *) |
628 | 628 |
703 (** %\vspace{-.15in}% [[ | 703 (** %\vspace{-.15in}% [[ |
704 t2 = | 704 t2 = |
705 fun P Q : Prop => | 705 fun P Q : Prop => |
706 comm_prem (assoc_prem1 (assoc_prem2 (False_prem (P:=P /\ P /\ Q) (P /\ Q)))) | 706 comm_prem (assoc_prem1 (assoc_prem2 (False_prem (P:=P /\ P /\ Q) (P /\ Q)))) |
707 : forall P Q : Prop, Q /\ (P /\ False) /\ P --> P /\ Q | 707 : forall P Q : Prop, Q /\ (P /\ False) /\ P --> P /\ Q |
708 | |
709 ]] | 708 ]] |
710 | 709 |
711 We can also see that [matcher] is well-suited for cases where some human intervention is needed after the automation finishes. *) | 710 %\smallskip{}%We can also see that [matcher] is well-suited for cases where some human intervention is needed after the automation finishes. *) |
712 | 711 |
713 Theorem t3 : forall P Q R : Prop, | 712 Theorem t3 : forall P Q R : Prop, |
714 P /\ Q --> Q /\ R /\ P. | 713 P /\ Q --> Q /\ R /\ P. |
715 matcher. | 714 matcher. |
716 (** [[ | 715 (** [[ |
967 | 966 |
968 Theorem t8 : exists p : nat * nat, fst p = 3. | 967 Theorem t8 : exists p : nat * nat, fst p = 3. |
969 econstructor; instantiate (1 := (3, 2)); reflexivity. | 968 econstructor; instantiate (1 := (3, 2)); reflexivity. |
970 Qed. | 969 Qed. |
971 | 970 |
972 (** The [1] above is identifying an existential variable appearing in the current goal, with the last existential appearing assigned number 1, the second last assigned number 2, and so on. The named existential is replaced everywhere by the term to the right of the [:=]. | 971 (** The [1] above is identifying an existential variable appearing in the current goal, with the last existential appearing assigned number 1, the second-last assigned number 2, and so on. The named existential is replaced everywhere by the term to the right of the [:=]. |
973 | 972 |
974 The %\index{tactics!instantiate}%[instantiate] tactic can be convenient for exploratory proving, but it leads to very brittle proof scripts that are unlikely to adapt to changing theorem statements. It is often more helpful to have a tactic that can be used to assign a value to a term that is known to be an existential. By employing a roundabout implementation technique, we can build a tactic that generalizes this functionality. In particular, our tactic [equate] will assert that two terms are equal. If one of the terms happens to be an existential, then it will be replaced everywhere with the other term. *) | 973 The %\index{tactics!instantiate}%[instantiate] tactic can be convenient for exploratory proving, but it leads to very brittle proof scripts that are unlikely to adapt to changing theorem statements. It is often more helpful to have a tactic that can be used to assign a value to a term that is known to be an existential. By employing a roundabout implementation technique, we can build a tactic that generalizes this functionality. In particular, our tactic [equate] will assert that two terms are equal. If one of the terms happens to be an existential, then it will be replaced everywhere with the other term. *) |
975 | 974 |
976 Ltac equate x y := | 975 Ltac equate x y := |
977 let H := fresh "H" in | 976 let dummy := constr:(eq_refl x : x = y) in idtac. |
978 assert (H : x = y) by reflexivity; clear H. | 977 |
979 | 978 (** This tactic fails if it is not possible to prove [x = y] by [eq_refl]. We check the proof only for its unification side effects, ignoring the associated variable [dummy]. With [equate], we can build a less brittle version of the prior example. *) |
980 (** This tactic fails if it is not possible to prove [x = y] by [reflexivity]. We perform the proof only for its unification side effects, clearing the fact [x = y] afterward. With [equate], we can build a less brittle version of the prior example. *) | |
981 | 979 |
982 Theorem t9 : exists p : nat * nat, fst p = 3. | 980 Theorem t9 : exists p : nat * nat, fst p = 3. |
983 econstructor; match goal with | 981 econstructor; match goal with |
984 | [ |- fst ?x = 3 ] => equate x (3, 2) | 982 | [ |- fst ?x = 3 ] => equate x (3, 2) |
985 end; reflexivity. | 983 end; reflexivity. |