Mercurial > cpdt > repo
comparison src/Equality.v @ 407:ff0aef0f33a5
Typesetting pass over Equality
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 08 Jun 2012 14:45:22 -0400 |
parents | 05efde66559d |
children | 5f25705a10ea |
comparison
equal
deleted
inserted
replaced
406:fc03a67810e8 | 407:ff0aef0f33a5 |
---|---|
21 (** In traditional mathematics, the concept of equality is usually taken as a given. On the other hand, in type theory, equality is a very contentious subject. There are at least three different notions of equality that are important, and researchers are actively investigating new definitions of what it means for two terms to be equal. Even once we fix a notion of equality, there are inevitably tricky issues that arise in proving properties of programs that manipulate equality proofs explicitly. In this chapter, I will focus on design patterns for circumventing these tricky issues, and I will introduce the different notions of equality as they are germane. *) | 21 (** In traditional mathematics, the concept of equality is usually taken as a given. On the other hand, in type theory, equality is a very contentious subject. There are at least three different notions of equality that are important, and researchers are actively investigating new definitions of what it means for two terms to be equal. Even once we fix a notion of equality, there are inevitably tricky issues that arise in proving properties of programs that manipulate equality proofs explicitly. In this chapter, I will focus on design patterns for circumventing these tricky issues, and I will introduce the different notions of equality as they are germane. *) |
22 | 22 |
23 | 23 |
24 (** * The Definitional Equality *) | 24 (** * The Definitional Equality *) |
25 | 25 |
26 (** We have seen many examples so far where proof goals follow %``%#"#by computation.#"#%''% That is, we apply computational reduction rules to reduce the goal to a normal form, at which point it follows trivially. Exactly when this works and when it does not depends on the details of Coq's %\index{definitional equality}%_definitional equality_. This is an untyped binary relation appearing in the formal metatheory of CIC. CIC contains a typing rule allowing the conclusion $E : T$ from the premise $E : T'$ and a proof that $T$ and $T'$ are definitionally equal. | 26 (** We have seen many examples so far where proof goals follow %``%#"#by computation.#"#%''% That is, we apply computational reduction rules to reduce the goal to a normal form, at which point it follows trivially. Exactly when this works and when it does not depends on the details of Coq's%\index{definitional equality}% _definitional equality_. This is an untyped binary relation appearing in the formal metatheory of CIC. CIC contains a typing rule allowing the conclusion $E : T$ from the premise $E : T'$ and a proof that $T$ and $T'$ are definitionally equal. |
27 | 27 |
28 The %\index{tactics!cbv}%[cbv] tactic will help us illustrate the rules of Coq's definitional equality. We redefine the natural number predecessor function in a somewhat convoluted way and construct a manual proof that it returns [0] when applied to [1]. *) | 28 The %\index{tactics!cbv}%[cbv] tactic will help us illustrate the rules of Coq's definitional equality. We redefine the natural number predecessor function in a somewhat convoluted way and construct a manual proof that it returns [0] when applied to [1]. *) |
29 | 29 |
30 Definition pred' (x : nat) := | 30 Definition pred' (x : nat) := |
31 match x with | 31 match x with |
165 | 165 |
166 Recall that co-recursive definitions have a dual rule: a co-recursive call only simplifies when it is the discriminee of a [match]. This condition is built into the beta rule for %\index{Gallina terms!cofix}%[cofix], the anonymous form of [CoFixpoint]. | 166 Recall that co-recursive definitions have a dual rule: a co-recursive call only simplifies when it is the discriminee of a [match]. This condition is built into the beta rule for %\index{Gallina terms!cofix}%[cofix], the anonymous form of [CoFixpoint]. |
167 | 167 |
168 %\medskip% | 168 %\medskip% |
169 | 169 |
170 The standard [eq] relation is critically dependent on the definitional equality. The relation [eq] is often called a %\index{propositional equality}%_propositional equality_, because it reifies definitional equality as a proposition that may or may not hold. Standard axiomatizations of an equality predicate in first-order logic define equality in terms of properties it has, like reflexivity, symmetry, and transitivity. In contrast, for [eq] in Coq, those properties are implicit in the properties of the definitional equality, which are built into CIC's metatheory and the implementation of Gallina. We could add new rules to the definitional equality, and [eq] would keep its definition and methods of use. | 170 The standard [eq] relation is critically dependent on the definitional equality. The relation [eq] is often called a%\index{propositional equality}% _propositional equality_, because it reifies definitional equality as a proposition that may or may not hold. Standard axiomatizations of an equality predicate in first-order logic define equality in terms of properties it has, like reflexivity, symmetry, and transitivity. In contrast, for [eq] in Coq, those properties are implicit in the properties of the definitional equality, which are built into CIC's metatheory and the implementation of Gallina. We could add new rules to the definitional equality, and [eq] would keep its definition and methods of use. |
171 | 171 |
172 This all may make it sound like the choice of [eq]'s definition is unimportant. To the contrary, in this chapter, we will see examples where alternate definitions may simplify proofs. Before that point, I will introduce proof methods for goals that use proofs of the standard propositional equality %``%#"#as data.#"#%''% *) | 172 This all may make it sound like the choice of [eq]'s definition is unimportant. To the contrary, in this chapter, we will see examples where alternate definitions may simplify proofs. Before that point, I will introduce proof methods for goals that use proofs of the standard propositional equality %``%#"#as data.#"#%''% *) |
173 | 173 |
174 | 174 |
175 (** * Heterogeneous Lists Revisited *) | 175 (** * Heterogeneous Lists Revisited *) |
271 | 271 |
272 In retrospect, the problem is not so hard to see. Reflexivity proofs only show [x = x] for particular values of [x], whereas here we are thinking in terms of a proof of [a = elm], where the two sides of the equality are not equal syntactically. Thus, the essential lemma we need does not even type-check! | 272 In retrospect, the problem is not so hard to see. Reflexivity proofs only show [x = x] for particular values of [x], whereas here we are thinking in terms of a proof of [a = elm], where the two sides of the equality are not equal syntactically. Thus, the essential lemma we need does not even type-check! |
273 | 273 |
274 Is it time to throw in the towel? Luckily, the answer is %``%#"#no.#"#%''% In this chapter, we will see several useful patterns for proving obligations like this. | 274 Is it time to throw in the towel? Luckily, the answer is %``%#"#no.#"#%''% In this chapter, we will see several useful patterns for proving obligations like this. |
275 | 275 |
276 For this particular example, the solution is surprisingly straightforward. [destruct] has a simpler sibling [case] which should behave identically for any inductive type with one constructor of no arguments. | 276 For this particular example, the solution is surprisingly straightforward. The [destruct] tactic has a simpler sibling [case] which should behave identically for any inductive type with one constructor of no arguments. |
277 [[ | 277 [[ |
278 case a0. | 278 case a0. |
279 | 279 |
280 ============================ | 280 ============================ |
281 f a1 = f a1 | 281 f a1 = f a1 |
468 "fhapp (ls1:=ls1 ++ ls2) (ls2:=ls3) (fhapp (ls1:=ls1) (ls2:=ls2) hls1 hls2) | 468 "fhapp (ls1:=ls1 ++ ls2) (ls2:=ls3) (fhapp (ls1:=ls1) (ls2:=ls2) hls1 hls2) |
469 hls3" has type "fhlist B ((ls1 ++ ls2) ++ ls3)" | 469 hls3" has type "fhlist B ((ls1 ++ ls2) ++ ls3)" |
470 while it is expected to have type "fhlist B (ls1 ++ ls2 ++ ls3)" | 470 while it is expected to have type "fhlist B (ls1 ++ ls2 ++ ls3)" |
471 >> | 471 >> |
472 | 472 |
473 This first cut at the theorem statement does not even type-check. We know that the two [fhlist] types appearing in the error message are always equal, by associativity of normal list append, but this fact is not apparent to the type checker. This stems from the fact that Coq's equality is %\index{intensional type theory}%_intensional_, in the sense that type equality theorems can never be applied after the fact to get a term to type-check. Instead, we need to make use of equality explicitly in the theorem statement. *) | 473 This first cut at the theorem statement does not even type-check. We know that the two [fhlist] types appearing in the error message are always equal, by associativity of normal list append, but this fact is not apparent to the type checker. This stems from the fact that Coq's equality is%\index{intensional type theory}% _intensional_, in the sense that type equality theorems can never be applied after the fact to get a term to type-check. Instead, we need to make use of equality explicitly in the theorem statement. *) |
474 | 474 |
475 Theorem fhapp_ass : forall ls1 ls2 ls3 | 475 Theorem fhapp_ass : forall ls1 ls2 ls3 |
476 (pf : (ls1 ++ ls2) ++ ls3 = ls1 ++ (ls2 ++ ls3)) | 476 (pf : (ls1 ++ ls2) ++ ls3 = ls1 ++ (ls2 ++ ls3)) |
477 (hls1 : fhlist B ls1) (hls2 : fhlist B ls2) (hls3 : fhlist B ls3), | 477 (hls1 : fhlist B ls1) (hls2 : fhlist B ls2) (hls3 : fhlist B ls3), |
478 fhapp hls1 (fhapp hls2 hls3) | 478 fhapp hls1 (fhapp hls2 hls3) |
636 (** This proof strategy was cumbersome and unorthodox, from the perspective of mainstream mathematics. The next section explores an alternative that leads to simpler developments in some cases. *) | 636 (** This proof strategy was cumbersome and unorthodox, from the perspective of mainstream mathematics. The next section explores an alternative that leads to simpler developments in some cases. *) |
637 | 637 |
638 | 638 |
639 (** * Heterogeneous Equality *) | 639 (** * Heterogeneous Equality *) |
640 | 640 |
641 (** There is another equality predicate, defined in the %\index{Gallina terms!JMeq}%[JMeq] module of the standard library, implementing %\index{heterogeneous equality}%_heterogeneous equality_. *) | 641 (** There is another equality predicate, defined in the %\index{Gallina terms!JMeq}%[JMeq] module of the standard library, implementing%\index{heterogeneous equality}% _heterogeneous equality_. *) |
642 | 642 |
643 Print JMeq. | 643 Print JMeq. |
644 (** %\vspace{-.15in}% [[ | 644 (** %\vspace{-.15in}% [[ |
645 Inductive JMeq (A : Type) (x : A) : forall B : Type, B -> Prop := | 645 Inductive JMeq (A : Type) (x : A) : forall B : Type, B -> Prop := |
646 JMeq_refl : JMeq x x | 646 JMeq_refl : JMeq x x |
647 ]] | 647 ]] |
648 | 648 |
649 The identity [JMeq] stands for %\index{John Major equality}``%#"#John Major equality,#"#%''% a name coined by Conor McBride%~\cite{JMeq}% as a sort of pun about British politics. [JMeq] starts out looking a lot like [eq]. The crucial difference is that we may use [JMeq] _on arguments of different types_. For instance, a lemma that we failed to establish before is trivial with [JMeq]. It makes for prettier theorem statements to define some syntactic shorthand first. *) | 649 The identity [JMeq] stands for %\index{John Major equality}``%#"#John Major equality,#"#%''% a name coined by Conor McBride%~\cite{JMeq}% as a sort of pun about British politics. The definition [JMeq] starts out looking a lot like the definition of [eq]. The crucial difference is that we may use [JMeq] _on arguments of different types_. For instance, a lemma that we failed to establish before is trivial with [JMeq]. It makes for prettier theorem statements to define some syntactic shorthand first. *) |
650 | 650 |
651 Infix "==" := JMeq (at level 70, no associativity). | 651 Infix "==" := JMeq (at level 70, no associativity). |
652 | 652 |
653 (* EX: Prove UIP_refl' : forall (A : Type) (x : A) (pf : x = x), pf == refl_equal x *) | 653 (* EX: Prove UIP_refl' : forall (A : Type) (x : A) (pf : x = x), pf == refl_equal x *) |
654 (* begin thide *) | 654 (* begin thide *) |
709 << | 709 << |
710 Error: Impossible to unify "fhlist B ((ls1 ++ ?1572) ++ ?1573)" with | 710 Error: Impossible to unify "fhlist B ((ls1 ++ ?1572) ++ ?1573)" with |
711 "fhlist B (ls1 ++ ?1572 ++ ?1573)" | 711 "fhlist B (ls1 ++ ?1572 ++ ?1573)" |
712 >> | 712 >> |
713 | 713 |
714 Coq 8.3 currently gives an error message about an uncaught exception. Perhaps that will be fixed soon. In any case, it is educational to consider a more explicit approach. | 714 Coq 8.4 currently gives an error message about an uncaught exception. Perhaps that will be fixed soon. In any case, it is educational to consider a more explicit approach. |
715 | 715 |
716 We see that [JMeq] is not a silver bullet. We can use it to simplify the statements of equality facts, but the Coq type-checker uses non-trivial heterogeneous equality facts no more readily than it uses standard equality facts. Here, the problem is that the form [(e1, e2)] is syntactic sugar for an explicit application of a constructor of an inductive type. That application mentions the type of each tuple element explicitly, and our [rewrite] tries to change one of those elements without updating the corresponding type argument. | 716 We see that [JMeq] is not a silver bullet. We can use it to simplify the statements of equality facts, but the Coq type-checker uses non-trivial heterogeneous equality facts no more readily than it uses standard equality facts. Here, the problem is that the form [(e1, e2)] is syntactic sugar for an explicit application of a constructor of an inductive type. That application mentions the type of each tuple element explicitly, and our [rewrite] tries to change one of those elements without updating the corresponding type argument. |
717 | 717 |
718 We can get around this problem by another multiple use of [generalize]. We want to bring into the goal the proper instance of the inductive hypothesis, and we also want to generalize the two relevant uses of [fhapp]. *) | 718 We can get around this problem by another multiple use of [generalize]. We want to bring into the goal the proper instance of the inductive hypothesis, and we also want to generalize the two relevant uses of [fhapp]. *) |
719 | 719 |
929 | 929 |
930 | 930 |
931 (** * Equality of Functions *) | 931 (** * Equality of Functions *) |
932 | 932 |
933 (** The following seems like a reasonable theorem to want to hold, and it does hold in set theory. [[ | 933 (** The following seems like a reasonable theorem to want to hold, and it does hold in set theory. [[ |
934 Theorem S_eta : S = (fun n => S n). | 934 Theorem two_identities : (fun n => n) = (fun n => n + 0). |
935 ]] | 935 ]] |
936 | 936 |
937 Unfortunately, this theorem is not provable in CIC without additional axioms. None of the definitional equality rules force function equality to be %\index{extensionality of function equality}%_extensional_. That is, the fact that two functions return equal results on equal inputs does not imply that the functions are equal. We _can_ assert function extensionality as an axiom. *) | 937 Unfortunately, this theorem is not provable in CIC without additional axioms. None of the definitional equality rules force function equality to be%\index{extensionality of function equality}% _extensional_. That is, the fact that two functions return equal results on equal inputs does not imply that the functions are equal. We _can_ assert function extensionality as an axiom, and indeed the standard library already contains that axiom. *) |
938 | 938 |
939 (* begin thide *) | 939 Require Import FunctionalExtensionality. |
940 Axiom ext_eq : forall A B (f g : A -> B), | 940 About functional_extensionality. |
941 (forall x, f x = g x) | 941 (** %\vspace{-.15in}%[[ |
942 -> f = g. | 942 functional_extensionality : |
943 (* end thide *) | 943 forall (A B : Type) (f g : A -> B), (forall x : A, f x = g x) -> f = g |
944 ]] | |
945 *) | |
944 | 946 |
945 (** This axiom has been verified metatheoretically to be consistent with CIC and the two equality axioms we considered previously. With it, the proof of [S_eta] is trivial. *) | 947 (** This axiom has been verified metatheoretically to be consistent with CIC and the two equality axioms we considered previously. With it, the proof of [S_eta] is trivial. *) |
946 | 948 |
947 Theorem S_eta : S = (fun n => S n). | 949 Theorem two_identities : (fun n => n) = (fun n => n + 0). |
948 (* begin thide *) | 950 (* begin thide *) |
949 apply ext_eq; reflexivity. | 951 apply functional_extensionality; crush. |
950 Qed. | 952 Qed. |
951 (* end thide *) | 953 (* end thide *) |
952 | 954 |
953 (** The same axiom can help us prove equality of types, where we need to %``%#"#reason under quantifiers.#"#%''% *) | 955 (** The same axiom can help us prove equality of types, where we need to %``%#"#reason under quantifiers.#"#%''% *) |
954 | 956 |
963 (* begin thide *) | 965 (* begin thide *) |
964 change ((forall x : nat, (fun x => match x with | 966 change ((forall x : nat, (fun x => match x with |
965 | 0 => True | 967 | 0 => True |
966 | S _ => True | 968 | S _ => True |
967 end) x) = (nat -> True)). | 969 end) x) = (nat -> True)). |
968 rewrite (ext_eq (fun x => match x with | 970 rewrite (functional_extensionality (fun x => match x with |
969 | 0 => True | 971 | 0 => True |
970 | S _ => True | 972 | S _ => True |
971 end) (fun _ => True)). | 973 end) (fun _ => True)). |
972 (** [[ | 974 (** [[ |
973 2 subgoals | 975 2 subgoals |
974 | 976 |
975 ============================ | 977 ============================ |
976 (nat -> True) = (nat -> True) | 978 (nat -> True) = (nat -> True) |
987 | 989 |
988 destruct x; constructor. | 990 destruct x; constructor. |
989 Qed. | 991 Qed. |
990 (* end thide *) | 992 (* end thide *) |
991 | 993 |
992 (** Unlike in the case of [eq_rect_eq], we have no way of deriving this axiom of %\index{functional extensionality}%_functional extensionality_ for types with decidable equality. To allow equality reasoning without axioms, it may be worth rewriting a development to replace functions with alternate representations, such as finite map types for which extensionality is derivable in CIC. *) | 994 (** Unlike in the case of [eq_rect_eq], we have no way of deriving this axiom of%\index{functional extensionality}% _functional extensionality_ for types with decidable equality. To allow equality reasoning without axioms, it may be worth rewriting a development to replace functions with alternate representations, such as finite map types for which extensionality is derivable in CIC. *) |