Mercurial > cpdt > repo
comparison src/InductiveTypes.v @ 442:89c67796754e
Undo some overzealous vspace tweaks
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 01 Aug 2012 16:09:37 -0400 |
parents | 393b8ed99c2f |
children | 2740b8a23cce |
comparison
equal
deleted
inserted
replaced
441:cbfd23b4364d | 442:89c67796754e |
---|---|
323 (** %\vspace{-.15in}% [[ | 323 (** %\vspace{-.15in}% [[ |
324 nat_ind : forall P : nat -> Prop, | 324 nat_ind : forall P : nat -> Prop, |
325 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n | 325 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
326 ]] | 326 ]] |
327 | 327 |
328 %\smallskip{}%Each of the two cases of our last proof came from the type of one of the arguments to [nat_ind]. We chose [P] to be [(fun n : nat => plus n O = n)]. The first proof case corresponded to [P O] and the second case to [(forall n : nat, P n -> P (S n))]. The free variable [n] and inductive hypothesis [IHn] came from the argument types given here. | 328 Each of the two cases of our last proof came from the type of one of the arguments to [nat_ind]. We chose [P] to be [(fun n : nat => plus n O = n)]. The first proof case corresponded to [P O] and the second case to [(forall n : nat, P n -> P (S n))]. The free variable [n] and inductive hypothesis [IHn] came from the argument types given here. |
329 | 329 |
330 Since [nat] has a constructor that takes an argument, we may sometimes need to know that that constructor is injective.%\index{tactics!injection}\index{tactics!trivial}% *) | 330 Since [nat] has a constructor that takes an argument, we may sometimes need to know that that constructor is injective.%\index{tactics!injection}\index{tactics!trivial}% *) |
331 | 331 |
332 Theorem S_inj : forall n m : nat, S n = S m -> n = m. | 332 Theorem S_inj : forall n m : nat, S n = S m -> n = m. |
333 (* begin thide *) | 333 (* begin thide *) |
499 (** %\vspace{-.15in}% [[ | 499 (** %\vspace{-.15in}% [[ |
500 Inductive list (T : Set) : Set := | 500 Inductive list (T : Set) : Set := |
501 Nil : list T | Cons : T -> list T -> list T | 501 Nil : list T | Cons : T -> list T -> list T |
502 ]] | 502 ]] |
503 | 503 |
504 %\smallskip{}%The final definition is the same as what we wrote manually before. The other elements of the section are altered similarly, turning out exactly as they were before, though we managed to write their definitions more succinctly. *) | 504 The final definition is the same as what we wrote manually before. The other elements of the section are altered similarly, turning out exactly as they were before, though we managed to write their definitions more succinctly. *) |
505 | 505 |
506 Check length. | 506 Check length. |
507 (** %\vspace{-.15in}% [[ | 507 (** %\vspace{-.15in}% [[ |
508 length | 508 length |
509 : forall T : Set, list T -> nat | 509 : forall T : Set, list T -> nat |
510 ]] | 510 ]] |
511 | 511 |
512 %\smallskip{}%The parameter [T] is treated as a new argument to the induction principle, too. *) | 512 The parameter [T] is treated as a new argument to the induction principle, too. *) |
513 | 513 |
514 Check list_ind. | 514 Check list_ind. |
515 (** %\vspace{-.15in}% [[ | 515 (** %\vspace{-.15in}% [[ |
516 list_ind | 516 list_ind |
517 : forall (T : Set) (P : list T -> Prop), | 517 : forall (T : Set) (P : list T -> Prop), |
518 P (Nil T) -> | 518 P (Nil T) -> |
519 (forall (t : T) (l : list T), P l -> P (Cons t l)) -> | 519 (forall (t : T) (l : list T), P l -> P (Cons t l)) -> |
520 forall l : list T, P l | 520 forall l : list T, P l |
521 ]] | 521 ]] |
522 | 522 |
523 %\smallskip{}%Thus, even though we just saw that [T] is added as an extra argument to the constructor [Cons], there is no quantifier for [T] in the type of the inductive case like there is for each of the other arguments. *) | 523 Thus, even though we just saw that [T] is added as an extra argument to the constructor [Cons], there is no quantifier for [T] in the type of the inductive case like there is for each of the other arguments. *) |
524 | 524 |
525 | 525 |
526 (** * Mutually Inductive Types *) | 526 (** * Mutually Inductive Types *) |
527 | 527 |
528 (** We can define inductive types that refer to each other: *) | 528 (** We can define inductive types that refer to each other: *) |
582 P ENil -> | 582 P ENil -> |
583 (forall (n : nat) (o : odd_list), P (ECons n o)) -> | 583 (forall (n : nat) (o : odd_list), P (ECons n o)) -> |
584 forall e : even_list, P e | 584 forall e : even_list, P e |
585 ]] | 585 ]] |
586 | 586 |
587 %\smallskip{}%We see that no inductive hypotheses are included anywhere in the type. To get them, we must ask for mutual principles as we need them, using the %\index{Vernacular commands!Scheme}%[Scheme] command. *) | 587 We see that no inductive hypotheses are included anywhere in the type. To get them, we must ask for mutual principles as we need them, using the %\index{Vernacular commands!Scheme}%[Scheme] command. *) |
588 | 588 |
589 Scheme even_list_mut := Induction for even_list Sort Prop | 589 Scheme even_list_mut := Induction for even_list Sort Prop |
590 with odd_list_mut := Induction for odd_list Sort Prop. | 590 with odd_list_mut := Induction for odd_list Sort Prop. |
591 | 591 |
592 (** This invocation of [Scheme] asks for the creation of induction principles [even_list_mut] for the type [even_list] and [odd_list_mut] for the type [odd_list]. The [Induction] keyword says we want standard induction schemes, since [Scheme] supports more exotic choices. Finally, [Sort Prop] establishes that we really want induction schemes, not recursion schemes, which are the same according to Curry-Howard, save for the [Prop]/[Set] distinction. *) | 592 (** This invocation of [Scheme] asks for the creation of induction principles [even_list_mut] for the type [even_list] and [odd_list_mut] for the type [odd_list]. The [Induction] keyword says we want standard induction schemes, since [Scheme] supports more exotic choices. Finally, [Sort Prop] establishes that we really want induction schemes, not recursion schemes, which are the same according to Curry-Howard, save for the [Prop]/[Set] distinction. *) |
693 (forall f1 : nat -> formula, | 693 (forall f1 : nat -> formula, |
694 (forall n : nat, P (f1 n)) -> P (Forall f1)) -> | 694 (forall n : nat, P (f1 n)) -> P (Forall f1)) -> |
695 forall f2 : formula, P f2 | 695 forall f2 : formula, P f2 |
696 ]] | 696 ]] |
697 | 697 |
698 %\smallskip{}%Focusing on the [Forall] case, which comes third, we see that we are allowed to assume that the theorem holds _for any application of the argument function [f1]_. That is, Coq induction principles do not follow a simple rule that the textual representations of induction variables must get shorter in appeals to induction hypotheses. Luckily for us, the people behind the metatheory of Coq have verified that this flexibility does not introduce unsoundness. | 698 Focusing on the [Forall] case, which comes third, we see that we are allowed to assume that the theorem holds _for any application of the argument function [f1]_. That is, Coq induction principles do not follow a simple rule that the textual representations of induction variables must get shorter in appeals to induction hypotheses. Luckily for us, the people behind the metatheory of Coq have verified that this flexibility does not introduce unsoundness. |
699 | 699 |
700 %\medskip% | 700 %\medskip% |
701 | 701 |
702 Up to this point, we have seen how to encode in Coq more and more of what is possible with algebraic datatypes in %\index{Haskell}%Haskell and %\index{ML}%ML. This may have given the inaccurate impression that inductive types are a strict extension of algebraic datatypes. In fact, Coq must rule out some types allowed by Haskell and ML, for reasons of soundness. Reflexive types provide our first good example of such a case. | 702 Up to this point, we have seen how to encode in Coq more and more of what is possible with algebraic datatypes in %\index{Haskell}%Haskell and %\index{ML}%ML. This may have given the inaccurate impression that inductive types are a strict extension of algebraic datatypes. In fact, Coq must rule out some types allowed by Haskell and ML, for reasons of soundness. Reflexive types provide our first good example of such a case. |
703 | 703 |
747 unit_ind = | 747 unit_ind = |
748 fun P : unit -> Prop => unit_rect P | 748 fun P : unit -> Prop => unit_rect P |
749 : forall P : unit -> Prop, P tt -> forall u : unit, P u | 749 : forall P : unit -> Prop, P tt -> forall u : unit, P u |
750 ]] | 750 ]] |
751 | 751 |
752 %\smallskip{}%We see that this induction principle is defined in terms of a more general principle, [unit_rect]. The <<rec>> stands for "recursion principle," and the <<t>> at the end stands for [Type]. *) | 752 We see that this induction principle is defined in terms of a more general principle, [unit_rect]. The <<rec>> stands for "recursion principle," and the <<t>> at the end stands for [Type]. *) |
753 | 753 |
754 Check unit_rect. | 754 Check unit_rect. |
755 (** %\vspace{-.15in}% [[ | 755 (** %\vspace{-.15in}% [[ |
756 unit_rect | 756 unit_rect |
757 : forall P : unit -> Type, P tt -> forall u : unit, P u | 757 : forall P : unit -> Type, P tt -> forall u : unit, P u |
758 ]] | 758 ]] |
759 | 759 |
760 %\smallskip{}%The principle [unit_rect] gives [P] type [unit -> Type] instead of [unit -> Prop]. [Type] is another universe, like [Set] and [Prop]. In fact, it is a common supertype of both. Later on, we will discuss exactly what the significances of the different universes are. For now, it is just important that we can use [Type] as a sort of meta-universe that may turn out to be either [Set] or [Prop]. We can see the symmetry inherent in the subtyping relationship by printing the definition of another principle that was generated for [unit] automatically: *) | 760 The principle [unit_rect] gives [P] type [unit -> Type] instead of [unit -> Prop]. [Type] is another universe, like [Set] and [Prop]. In fact, it is a common supertype of both. Later on, we will discuss exactly what the significances of the different universes are. For now, it is just important that we can use [Type] as a sort of meta-universe that may turn out to be either [Set] or [Prop]. We can see the symmetry inherent in the subtyping relationship by printing the definition of another principle that was generated for [unit] automatically: *) |
761 | 761 |
762 Print unit_rec. | 762 Print unit_rec. |
763 (** %\vspace{-.15in}%[[ | 763 (** %\vspace{-.15in}%[[ |
764 unit_rec = | 764 unit_rec = |
765 fun P : unit -> Set => unit_rect P | 765 fun P : unit -> Set => unit_rect P |
766 : forall P : unit -> Set, P tt -> forall u : unit, P u | 766 : forall P : unit -> Set, P tt -> forall u : unit, P u |
767 ]] | 767 ]] |
768 | 768 |
769 %\smallskip{}%This is identical to the definition for [unit_ind], except that we have substituted [Set] for [Prop]. For most inductive types [T], then, we get not just induction principles [T_ind], but also %\index{recursion principles}%recursion principles [T_rec]. We can use [T_rec] to write recursive definitions without explicit [Fixpoint] recursion. For instance, the following two definitions are equivalent: *) | 769 This is identical to the definition for [unit_ind], except that we have substituted [Set] for [Prop]. For most inductive types [T], then, we get not just induction principles [T_ind], but also %\index{recursion principles}%recursion principles [T_rec]. We can use [T_rec] to write recursive definitions without explicit [Fixpoint] recursion. For instance, the following two definitions are equivalent: *) |
770 | 770 |
771 Definition always_O (u : unit) : nat := | 771 Definition always_O (u : unit) : nat := |
772 match u with | 772 match u with |
773 | tt => O | 773 | tt => O |
774 end. | 774 end. |
786 | tt => f | 786 | tt => f |
787 end | 787 end |
788 : forall P : unit -> Type, P tt -> forall u : unit, P u | 788 : forall P : unit -> Type, P tt -> forall u : unit, P u |
789 ]] | 789 ]] |
790 | 790 |
791 %\smallskip{}%The only new wrinkle here is the annotations on the [match] expression. This is a%\index{dependent pattern matching}% _dependently typed_ pattern match, because the _type_ of the expression depends on the _value_ being matched on. Of course, for this example, the dependency is degenerate; the value being matched on has type [unit], so it may only take on a single known value, [tt]. We will meet more involved examples later, especially in Part II of the book. | 791 The only new wrinkle here is the annotations on the [match] expression. This is a%\index{dependent pattern matching}% _dependently typed_ pattern match, because the _type_ of the expression depends on the _value_ being matched on. Of course, for this example, the dependency is degenerate; the value being matched on has type [unit], so it may only take on a single known value, [tt]. We will meet more involved examples later, especially in Part II of the book. |
792 | 792 |
793 %\index{type inference}%Type inference for dependent pattern matching is undecidable, which can be proved by reduction from %\index{higher-order unification}%higher-order unification%~\cite{HOU}%. Thus, we often find ourselves needing to annotate our programs in a way that explains dependencies to the type checker. In the example of [unit_rect], we have an %\index{Gallina terms!as}%[as] clause, which binds a name for the discriminee; and a %\index{Gallina terms!return}%[return] clause, which gives a way to compute the [match] result type as a function of the discriminee. | 793 %\index{type inference}%Type inference for dependent pattern matching is undecidable, which can be proved by reduction from %\index{higher-order unification}%higher-order unification%~\cite{HOU}%. Thus, we often find ourselves needing to annotate our programs in a way that explains dependencies to the type checker. In the example of [unit_rect], we have an %\index{Gallina terms!as}%[as] clause, which binds a name for the discriminee; and a %\index{Gallina terms!return}%[return] clause, which gives a way to compute the [match] result type as a function of the discriminee. |
794 | 794 |
795 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) | 795 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) |
796 | 796 |
820 end | 820 end |
821 : forall P : nat -> Type, | 821 : forall P : nat -> Type, |
822 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n | 822 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
823 ]] | 823 ]] |
824 | 824 |
825 %\smallskip{}%Now we have an actual recursive definition. Expressions starting with %\index{Gallina terms!fix}%[fix] are anonymous forms of [Fixpoint], just as [fun] expressions stand for anonymous non-recursive functions. Beyond that, the syntax of [fix] mirrors that of [Fixpoint]. We can understand the definition of [nat_rect] better by reimplementing [nat_ind] using sections. *) | 825 Now we have an actual recursive definition. Expressions starting with %\index{Gallina terms!fix}%[fix] are anonymous forms of [Fixpoint], just as [fun] expressions stand for anonymous non-recursive functions. Beyond that, the syntax of [fix] mirrors that of [Fixpoint]. We can understand the definition of [nat_rect] better by reimplementing [nat_ind] using sections. *) |
826 | 826 |
827 Section nat_ind'. | 827 Section nat_ind'. |
828 (** First, we have the property of natural numbers that we aim to prove. *) | 828 (** First, we have the property of natural numbers that we aim to prove. *) |
829 | 829 |
830 Variable P : nat -> Prop. | 830 Variable P : nat -> Prop. |
873 (forall (n : nat) (o : odd_list), P0 o -> P (ECons n o)) -> | 873 (forall (n : nat) (o : odd_list), P0 o -> P (ECons n o)) -> |
874 (forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) -> | 874 (forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) -> |
875 forall e : even_list, P e | 875 forall e : even_list, P e |
876 ]] | 876 ]] |
877 | 877 |
878 %\smallskip{}%We see a mutually recursive [fix], with the different functions separated by %\index{Gallina terms!with}%[with] in the same way that they would be separated by <<and>> in ML. A final %\index{Gallina terms!for}%[for] clause identifies which of the mutually recursive functions should be the final value of the [fix] expression. Using this definition as a template, we can reimplement [even_list_mut] directly. *) | 878 We see a mutually recursive [fix], with the different functions separated by %\index{Gallina terms!with}%[with] in the same way that they would be separated by <<and>> in ML. A final %\index{Gallina terms!for}%[for] clause identifies which of the mutually recursive functions should be the final value of the [fix] expression. Using this definition as a template, we can reimplement [even_list_mut] directly. *) |
879 | 879 |
880 Section even_list_mut'. | 880 Section even_list_mut'. |
881 (** First, we need the properties that we are proving. *) | 881 (** First, we need the properties that we are proving. *) |
882 | 882 |
883 Variable Peven : even_list -> Prop. | 883 Variable Peven : even_list -> Prop. |
942 P NLeaf' -> | 942 P NLeaf' -> |
943 (forall (n : nat) (l : list nat_tree), P (NNode' n l)) -> | 943 (forall (n : nat) (l : list nat_tree), P (NNode' n l)) -> |
944 forall n : nat_tree, P n | 944 forall n : nat_tree, P n |
945 ]] | 945 ]] |
946 | 946 |
947 %\smallskip{}%There is no command like [Scheme] that will implement an improved principle for us. In general, it takes creativity to figure out how to incorporate nested uses of different type families. This is roughly the same creativity employed in the traditional task of strengthening an induction hypothesis. Now that we know how to implement induction principles manually, we are in a position to apply just such creativity to this problem. | 947 There is no command like [Scheme] that will implement an improved principle for us. In general, it takes creativity to figure out how to incorporate nested uses of different type families. This is roughly the same creativity employed in the traditional task of strengthening an induction hypothesis. Now that we know how to implement induction principles manually, we are in a position to apply just such creativity to this problem. |
948 | 948 |
949 First, we will need an auxiliary definition, characterizing what it means for a property to hold of every element of a list. *) | 949 First, we will need an auxiliary definition, characterizing what it means for a property to hold of every element of a list. *) |
950 | 950 |
951 Section All. | 951 Section All. |
952 Variable T : Set. | 952 Variable T : Set. |
964 Print True. | 964 Print True. |
965 (** %\vspace{-.15in}%[[ | 965 (** %\vspace{-.15in}%[[ |
966 Inductive True : Prop := I : True | 966 Inductive True : Prop := I : True |
967 ]] | 967 ]] |
968 | 968 |
969 %\smallskip{}%That is, [True] is a proposition with exactly one proof, [I], which we may always supply trivially. | 969 That is, [True] is a proposition with exactly one proof, [I], which we may always supply trivially. |
970 | 970 |
971 Finding the definition of [/\] takes a little more work. Coq supports user registration of arbitrary parsing rules, and it is such a rule that is letting us write [/\] instead of an application of some inductive type family. We can find the underlying inductive type with the %\index{Vernacular commands!Locate}%[Locate] command, whose argument may be a parsing token.%\index{Gallina terms!and}% *) | 971 Finding the definition of [/\] takes a little more work. Coq supports user registration of arbitrary parsing rules, and it is such a rule that is letting us write [/\] instead of an application of some inductive type family. We can find the underlying inductive type with the %\index{Vernacular commands!Locate}%[Locate] command, whose argument may be a parsing token.%\index{Gallina terms!and}% *) |
972 | 972 |
973 Locate "/\". | 973 Locate "/\". |
974 (** %\vspace{-.15in}%[[ | 974 (** %\vspace{-.15in}%[[ |
1018 | Nil => I | 1018 | Nil => I |
1019 | Cons tr rest => conj (nat_tree_ind' tr) (list_nat_tree_ind rest) | 1019 | Cons tr rest => conj (nat_tree_ind' tr) (list_nat_tree_ind rest) |
1020 end. | 1020 end. |
1021 ]] | 1021 ]] |
1022 | 1022 |
1023 %\smallskip{}%Coq rejects this definition, saying | 1023 Coq rejects this definition, saying |
1024 << | 1024 << |
1025 Recursive call to nat_tree_ind' has principal argument equal to "tr" | 1025 Recursive call to nat_tree_ind' has principal argument equal to "tr" |
1026 instead of rest. | 1026 instead of rest. |
1027 >> | 1027 >> |
1028 | 1028 |
1148 (** %\vspace{-.15in}%[[ | 1148 (** %\vspace{-.15in}%[[ |
1149 ============================ | 1149 ============================ |
1150 true = false -> False | 1150 true = false -> False |
1151 ]] | 1151 ]] |
1152 | 1152 |
1153 %\smallskip{}%The negation is replaced with an implication of falsehood. We use the tactic %\index{tactics!intro}%[intro H] to change the assumption of the implication into a hypothesis named [H]. *) | 1153 The negation is replaced with an implication of falsehood. We use the tactic %\index{tactics!intro}%[intro H] to change the assumption of the implication into a hypothesis named [H]. *) |
1154 | 1154 |
1155 intro H. | 1155 intro H. |
1156 (** %\vspace{-.15in}%[[ | 1156 (** %\vspace{-.15in}%[[ |
1157 H : true = false | 1157 H : true = false |
1158 ============================ | 1158 ============================ |
1159 False | 1159 False |
1160 ]] | 1160 ]] |
1161 | 1161 |
1162 %\smallskip{}%This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *) | 1162 This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *) |
1163 | 1163 |
1164 Definition toProp (b : bool) := if b then True else False. | 1164 Definition toProp (b : bool) := if b then True else False. |
1165 | 1165 |
1166 (** It is worth recalling the difference between the lowercase and uppercase versions of truth and falsehood: [True] and [False] are logical propositions, while [true] and [false] are boolean values that we can case-analyze. We have defined [toProp] such that our conclusion of [False] is computationally equivalent to [toProp false]. Thus, the %\index{tactics!change}%[change] tactic will let us change the conclusion to [toProp false]. The general form [change e] replaces the conclusion with [e], whenever Coq's built-in computation rules suffice to establish the equivalence of [e] with the original conclusion. *) | 1166 (** It is worth recalling the difference between the lowercase and uppercase versions of truth and falsehood: [True] and [False] are logical propositions, while [true] and [false] are boolean values that we can case-analyze. We have defined [toProp] such that our conclusion of [False] is computationally equivalent to [toProp false]. Thus, the %\index{tactics!change}%[change] tactic will let us change the conclusion to [toProp false]. The general form [change e] replaces the conclusion with [e], whenever Coq's built-in computation rules suffice to establish the equivalence of [e] with the original conclusion. *) |
1167 | 1167 |
1170 H : true = false | 1170 H : true = false |
1171 ============================ | 1171 ============================ |
1172 toProp false | 1172 toProp false |
1173 ]] | 1173 ]] |
1174 | 1174 |
1175 %\smallskip{}%Now the righthand side of [H]'s equality appears in the conclusion, so we can rewrite, using the notation [<-] to request to replace the righthand side the equality with the lefthand side.%\index{tactics!rewrite}% *) | 1175 Now the righthand side of [H]'s equality appears in the conclusion, so we can rewrite, using the notation [<-] to request to replace the righthand side the equality with the lefthand side.%\index{tactics!rewrite}% *) |
1176 | 1176 |
1177 rewrite <- H. | 1177 rewrite <- H. |
1178 (** %\vspace{-.15in}%[[ | 1178 (** %\vspace{-.15in}%[[ |
1179 H : true = false | 1179 H : true = false |
1180 ============================ | 1180 ============================ |
1181 toProp true | 1181 toProp true |
1182 ]] | 1182 ]] |
1183 | 1183 |
1184 %\smallskip{}%We are almost done. Just how close we are to done is revealed by computational simplification. *) | 1184 We are almost done. Just how close we are to done is revealed by computational simplification. *) |
1185 | 1185 |
1186 simpl. | 1186 simpl. |
1187 (** %\vspace{-.15in}%[[ | 1187 (** %\vspace{-.15in}%[[ |
1188 H : true = false | 1188 H : true = false |
1189 ============================ | 1189 ============================ |