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