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. *)