Mercurial > cpdt > repo
comparison src/Equality.v @ 385:bef6fb896edd
More discussion of axiom avoidance and tactic pitfalls for JMeq
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 12 Apr 2012 12:11:29 -0400 |
parents | 549d604c3d16 |
children | 05efde66559d |
comparison
equal
deleted
inserted
replaced
384:eb0fa506d04c | 385:bef6fb896edd |
---|---|
737 From this point, the goal is trivial. *) | 737 From this point, the goal is trivial. *) |
738 | 738 |
739 intros f f0 H; rewrite H; reflexivity. | 739 intros f f0 H; rewrite H; reflexivity. |
740 Qed. | 740 Qed. |
741 (* end thide *) | 741 (* end thide *) |
742 End fhapp'. | 742 |
743 | 743 End fhapp'. |
744 (** This example illustrates a general pattern: heterogeneous equality often simplifies theorem statements, but we still need to do some work to line up some dependent pattern matches that tactics will generate for us. *) | 744 |
745 (** This example illustrates a general pattern: heterogeneous equality often simplifies theorem statements, but we still need to do some work to line up some dependent pattern matches that tactics will generate for us. | |
746 | |
747 The proof we have found relies on the [JMeq_eq] axiom, which we can verify with a command%\index{Vernacular commands!Print Assumptions}% that we will discuss more in two chapters. *) | |
748 | |
749 Print Assumptions fhapp_ass'. | |
750 (** %\vspace{-.15in}%[[ | |
751 Axioms: | |
752 JMeq_eq : forall (A : Type) (x y : A), x == y -> x = y | |
753 ]] | |
754 | |
755 It was the [rewrite H] tactic that implicitly appealed to the axiom. By restructuring the proof, we can avoid axiom dependence. A general lemma about pairs provides the key element. (Our use of [generalize] above can be thought of as reducing the proof to another, more complex and specialized lemma.) *) | |
756 | |
757 Lemma pair_cong : forall A1 A2 B1 B2 (x1 : A1) (x2 : A2) (y1 : B1) (y2 : B2), | |
758 x1 == x2 | |
759 -> y1 == y2 | |
760 -> (x1, y1) == (x2, y2). | |
761 intros until y2; intros Hx Hy; rewrite Hx; rewrite Hy; reflexivity. | |
762 Qed. | |
763 | |
764 Hint Resolve pair_cong. | |
765 | |
766 Section fhapp''. | |
767 Variable A : Type. | |
768 Variable B : A -> Type. | |
769 | |
770 Theorem fhapp_ass'' : forall ls1 ls2 ls3 (hls1 : fhlist B ls1) (hls2 : fhlist B ls2) | |
771 (hls3 : fhlist B ls3), | |
772 fhapp hls1 (fhapp hls2 hls3) == fhapp (fhapp hls1 hls2) hls3. | |
773 induction ls1; crush. | |
774 Qed. | |
775 End fhapp''. | |
776 | |
777 Print Assumptions fhapp_ass''. | |
778 (** << | |
779 Closed under the global context | |
780 >> | |
781 | |
782 One might wonder exactly which elements of a proof involving [JMeq] imply that [JMeq_eq] must be used. For instance, above we noticed that [rewrite] had brought [JMeq_eq] into the proof of [fhap_ass'], yet here we have also used [rewrite] with [JMeq] hypotheses while avoiding axioms! One illuminating exercise is comparing the types of the lemmas that [rewrite] uses under the hood to implement the rewrites. Here is the normal lemma for [eq] rewriting:%\index{Gallina terms!eq\_ind\_r}% *) | |
783 | |
784 Check eq_ind_r. | |
785 (** %\vspace{-.15in}%[[ | |
786 eq_ind_r | |
787 : forall (A : Type) (x : A) (P : A -> Prop), | |
788 P x -> forall y : A, y = x -> P y | |
789 ]] | |
790 | |
791 The corresponding lemma used for [JMeq] in the proof of [pair_cong] is %\index{Gallina terms!JMeq\_rew\_r}%[JMeq_rew_r], which, confusingly, is defined by [rewrite] as needed, so it is not available for checking until after we apply it. *) | |
792 | |
793 Check JMeq_rew_r. | |
794 (** %\vspace{-.15in}%[[ | |
795 JMeq_rew_r | |
796 : forall (A : Type) (x : A) (B : Type) (b : B) | |
797 (P : forall B0 : Type, B0 -> Type), P B b -> x == b -> P A x | |
798 ]] | |
799 | |
800 The key difference is that, where the [eq] lemma is parametrized on a predicate of type [A -> Prop], the [JMeq] lemma is parameterized on a predicate of type more like [forall A : Type, A -> Prop]. To apply [eq_ind_r] with a proof of [x = y], it is only necessary to rearrange the goal into an application of a [fun] abstraction to [y]. In contrast, to apply [JMeq_rew_r], it is necessary to rearrange the goal to an application of a [fun] abstraction to both [y] and %\emph{%#<i>#its type#</i>#%}%. In other words, the predicate must be %\emph{%#<i>#polymorphic#</i>#%}% in [y]'s type; any type must make sense, from a type-checking standpoint. There may be cases where the former rearrangement is easy to do in a type-correct way, but the second rearrangement done naively leads to a type error. | |
801 | |
802 When [rewrite] cannot figure out how to apply [JMeq_rew_r] for [x == y] where [x] and [y] have the same type, the tactic can instead use an alternate theorem, which is easy to prove as a composition of [eq_ind_r] and [JMeq_eq]. *) | |
803 | |
804 Check JMeq_ind_r. | |
805 (** %\vspace{-.15in}%[[ | |
806 JMeq_ind_r | |
807 : forall (A : Type) (x : A) (P : A -> Prop), | |
808 P x -> forall y : A, y == x -> P y | |
809 ]] | |
810 | |
811 Ironically, where in the proof of [fhapp_ass'] we used [rewrite app_ass] to make it clear that a use of [JMeq] was actually homogeneously typed, we created a situation where [rewrite] applied the axiom-based [JMeq_ind_r] instead of the axiom-free [JMeq_rew_r]! | |
812 | |
813 For another simple example, consider this theorem that applies a heterogeneous equality to prove a congruence fact. *) | |
814 | |
815 Theorem out_of_luck : forall n m : nat, | |
816 n == m | |
817 -> S n == S m. | |
818 intros n m H. | |
819 | |
820 (** Applying [JMeq_ind_r] is easy, as the %\index{tactics!pattern}%[pattern] tactic will transform the goal into an application of an appropriate [fun] to a term that we want to abstract. *) | |
821 | |
822 pattern n. | |
823 (** %\vspace{-.15in}%[[ | |
824 n : nat | |
825 m : nat | |
826 H : n == m | |
827 ============================ | |
828 (fun n0 : nat => S n0 == S m) n | |
829 ]] | |
830 *) | |
831 apply JMeq_ind_r with (x := m); auto. | |
832 | |
833 (** However, we run into trouble trying to get the goal into a form compatible with [JMeq_rew_r.] *) | |
834 Undo 2. | |
835 (** %\vspace{-.15in}%[[ | |
836 pattern nat, n. | |
837 ]] | |
838 << | |
839 Error: The abstracted term "fun (P : Set) (n0 : P) => S n0 == S m" | |
840 is not well typed. | |
841 Illegal application (Type Error): | |
842 The term "S" of type "nat -> nat" | |
843 cannot be applied to the term | |
844 "n0" : "P" | |
845 This term has type "P" which should be coercible to | |
846 "nat". | |
847 >> | |
848 | |
849 In other words, the successor function [S] is insufficiently polymorphic. If we try to generalize over the type of [n], we find that [S] is no longer legal to apply to [n]. *) | |
850 | |
851 Abort. | |
852 | |
853 (** Why did we not run into this problem in our proof of [fhapp_ass'']? The reason is that the pair constructor is polymorphic in the types of the pair components, while functions like [S] are not polymorphic at all. Use of such non-polymorphic functions with [JMeq] tends to push toward use of axioms. The example with [nat] here is a bit unrealistic; more likely cases would involve functions that have %\emph{%#<i>#some#</i>#%}% polymorphism, but not enough to allow abstractions of the sort we attempted above with [pattern]. For instance, we might have an equality between two lists, where the goal only type-checks when the terms involved really are lists, though everything is polymorphic in the types of list data elements. The #<a href="http://www.mpi-sws.org/~gil/Heq/">#Heq%\footnote{\url{http://www.mpi-sws.org/~gil/Heq/}}%#</a># library builds up a slightly different foundation to help avoid such problems. *) | |
745 | 854 |
746 | 855 |
747 (** * Equivalence of Equality Axioms *) | 856 (** * Equivalence of Equality Axioms *) |
748 | 857 |
749 (* EX: Show that the approaches based on K and JMeq are equivalent logically. *) | 858 (* EX: Show that the approaches based on K and JMeq are equivalent logically. *) |