Mercurial > cpdt > repo
comparison src/InductiveTypes.v @ 470:0df6dde807ab
Batch of changes based on proofreader feedback
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Tue, 02 Oct 2012 11:34:40 -0400 |
parents | b36876d4611e |
children | 51a8472aca68 |
comparison
equal
deleted
inserted
replaced
469:b36876d4611e | 470:0df6dde807ab |
---|---|
332 | 332 |
333 Inductive nat_list : Set := | 333 Inductive nat_list : Set := |
334 | NNil : nat_list | 334 | NNil : nat_list |
335 | NCons : nat -> nat_list -> nat_list. | 335 | NCons : nat -> nat_list -> nat_list. |
336 | 336 |
337 (** Recursive definitions are straightforward extensions of what we have seen before. *) | 337 (** Recursive definitions over [nat_list] are straightforward extensions of what we have seen before. *) |
338 | 338 |
339 Fixpoint nlength (ls : nat_list) : nat := | 339 Fixpoint nlength (ls : nat_list) : nat := |
340 match ls with | 340 match ls with |
341 | NNil => O | 341 | NNil => O |
342 | NCons _ ls' => S (nlength ls') | 342 | NCons _ ls' => S (nlength ls') |
623 (* begin thide *) | 623 (* begin thide *) |
624 Definition prod' := prod. | 624 Definition prod' := prod. |
625 (* end thide *) | 625 (* end thide *) |
626 (* end hide *) | 626 (* end hide *) |
627 | 627 |
628 (** A key distinction here is between, for instance, the _syntax_ [Truth] and its _semantics_ [True]. We can make the semantics explicit with a recursive function. This function uses the infix operator %\index{Gallina operators!/\textbackslash}%[/\], which desugared to uses of the type family %\index{Gallina terms!and}%[and] from the standard library. The family [and] implements conjunction, the [Prop] Curry-Howard analogue of the usual pair type from functional programming (which is the type family %\index{Gallina terms!prod}%[prod] in Coq's standard library). *) | 628 (** A key distinction here is between, for instance, the _syntax_ [Truth] and its _semantics_ [True]. We can make the semantics explicit with a recursive function. This function uses the infix operator %\index{Gallina operators!/\textbackslash}%[/\], which desugars to uses of the type family %\index{Gallina terms!and}%[and] from the standard library. The family [and] implements conjunction, the [Prop] Curry-Howard analogue of the usual pair type from functional programming (which is the type family %\index{Gallina terms!prod}%[prod] in Coq's standard library). *) |
629 | 629 |
630 Fixpoint pformulaDenote (f : pformula) : Prop := | 630 Fixpoint pformulaDenote (f : pformula) : Prop := |
631 match f with | 631 match f with |
632 | Truth => True | 632 | Truth => True |
633 | Falsehood => False | 633 | Falsehood => False |
639 Inductive formula : Set := | 639 Inductive formula : Set := |
640 | Eq : nat -> nat -> formula | 640 | Eq : nat -> nat -> formula |
641 | And : formula -> formula -> formula | 641 | And : formula -> formula -> formula |
642 | Forall : (nat -> formula) -> formula. | 642 | Forall : (nat -> formula) -> formula. |
643 | 643 |
644 (** Our kinds of formulas are equalities between naturals, conjunction, and universal quantification over natural numbers. We avoid needing to include a notion of "variables" in our type, by using Coq functions to encode quantification. For instance, here is the encoding of [forall x : nat, x = x]:%\index{Vernacular commands!Example}% *) | 644 (** Our kinds of formulas are equalities between naturals, conjunction, and universal quantification over natural numbers. We avoid needing to include a notion of "variables" in our type, by using Coq functions to encode the syntax of quantification. For instance, here is the encoding of [forall x : nat, x = x]:%\index{Vernacular commands!Example}% *) |
645 | 645 |
646 Example forall_refl : formula := Forall (fun x => Eq x x). | 646 Example forall_refl : formula := Forall (fun x => Eq x x). |
647 | 647 |
648 (** We can write recursive functions over reflexive types quite naturally. Here is one translating our formulas into native Coq propositions. *) | 648 (** We can write recursive functions over reflexive types quite naturally. Here is one translating our formulas into native Coq propositions. *) |
649 | 649 |
730 | 730 |
731 (** * An Interlude on Induction Principles *) | 731 (** * An Interlude on Induction Principles *) |
732 | 732 |
733 (** As we have emphasized a few times already, Coq proofs are actually programs, written in the same language we have been using in our examples all along. We can get a first sense of what this means by taking a look at the definitions of some of the %\index{induction principles}%induction principles we have used. A close look at the details here will help us construct induction principles manually, which we will see is necessary for some more advanced inductive definitions. *) | 733 (** As we have emphasized a few times already, Coq proofs are actually programs, written in the same language we have been using in our examples all along. We can get a first sense of what this means by taking a look at the definitions of some of the %\index{induction principles}%induction principles we have used. A close look at the details here will help us construct induction principles manually, which we will see is necessary for some more advanced inductive definitions. *) |
734 | 734 |
735 Print unit_ind. | 735 Print nat_ind. |
736 (** %\vspace{-.15in}%[[ | 736 (** %\vspace{-.15in}%[[ |
737 unit_ind = | 737 nat_ind = |
738 fun P : unit -> Prop => unit_rect P | 738 fun P : nat -> Prop => nat_rect P |
739 : forall P : unit -> Prop, P tt -> forall u : unit, P u | 739 : forall P : nat -> Prop, |
740 ]] | 740 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
741 | 741 ]] |
742 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]. *) | 742 |
743 | 743 We see that this induction principle is defined in terms of a more general principle, [nat_rect]. The <<rec>> stands for "recursion principle," and the <<t>> at the end stands for [Type]. *) |
744 Check unit_rect. | 744 |
745 Check nat_rect. | |
745 (** %\vspace{-.15in}% [[ | 746 (** %\vspace{-.15in}% [[ |
746 unit_rect | 747 nat_rect |
747 : forall P : unit -> Type, P tt -> forall u : unit, P u | 748 : forall P : nat -> Type, |
748 ]] | 749 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
749 | 750 ]] |
750 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: *) | 751 |
751 | 752 The principle [nat_rect] gives [P] type [nat -> Type] instead of [nat -> Prop]. This [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 [nat] automatically: *) |
752 Print unit_rec. | 753 |
754 Print nat_rec. | |
753 (** %\vspace{-.15in}%[[ | 755 (** %\vspace{-.15in}%[[ |
754 unit_rec = | 756 nat_rec = |
755 fun P : unit -> Set => unit_rect P | 757 fun P : nat -> Set => nat_rect P |
756 : forall P : unit -> Set, P tt -> forall u : unit, P u | 758 : forall P : nat -> Set, |
757 ]] | 759 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
758 | 760 ]] |
759 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: *) | 761 |
760 | 762 This is identical to the definition for [nat_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: *) |
761 Definition always_O (u : unit) : nat := | 763 |
762 match u with | 764 Fixpoint plus_recursive (n : nat) : nat -> nat := |
763 | tt => O | 765 match n with |
764 end. | 766 | O => fun m => m |
765 | 767 | S n' => fun m => S (plus_recursive n' m) |
766 Definition always_O' (u : unit) : nat := | 768 end. |
767 unit_rec (fun _ : unit => nat) O u. | 769 |
768 | 770 Definition plus_rec : nat -> nat -> nat := |
769 (** Going even further down the rabbit hole, [unit_rect] itself is not even a primitive. It is a functional program that we can write manually. *) | 771 nat_rec (fun _ : nat => nat -> nat) (fun _ => O) (fun _ r m => S (r m)). |
770 | 772 |
771 Print unit_rect. | 773 (** Going even further down the rabbit hole, [nat_rect] itself is not even a primitive. It is a functional program that we can write manually. *) |
774 | |
775 Print nat_rect. | |
772 (** %\vspace{-.15in}%[[ | 776 (** %\vspace{-.15in}%[[ |
773 unit_rect = | 777 nat_rect = |
774 fun (P : unit -> Type) (f : P tt) (u : unit) => | 778 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) => |
775 match u as u0 return (P u0) with | 779 fix F (n : nat) : P n := |
776 | tt => f | 780 match n as n0 return (P n0) with |
781 | O => f | |
782 | S n0 => f0 n0 (F n0) | |
777 end | 783 end |
778 : forall P : unit -> Type, P tt -> forall u : unit, P u | 784 : forall P : nat -> Type, |
779 ]] | 785 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n |
780 | 786 ]] |
781 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. | 787 |
782 | 788 The only new wrinkle heres are, first, an anonymous recursive function definition, using the %\index{Gallina terms!fix}%[fix] keyword of Gallina (which is like [fun] with recursion supported); and, second, 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. We will meet more involved examples later, especially in Part II of the book. |
783 %\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. | 789 |
784 | 790 %\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 [nat_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. |
785 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) | 791 |
786 | 792 To prove that [nat_rect] is nothing special, we can reimplement it manually. *) |
787 Definition unit_rect' (P : unit -> Type) (f : P tt) (u : unit) := | 793 |
788 match u return P u with | 794 Fixpoint nat_rect' (P : nat -> Type) |
789 | tt => f | 795 (HO : P O) |
790 end. | 796 (HS : forall n, P n -> P (S n)) (n : nat) := |
791 | 797 match n return P n with |
792 (* begin hide *) | 798 | O => HO |
793 (* begin thide *) | 799 | S n' => HS n' (nat_rect' P HO HS n') |
794 Definition foo := nat_rect. | 800 end. |
795 (* end thide *) | 801 |
796 (* end hide *) | 802 (** We can understand the definition of [nat_rect] better by reimplementing [nat_ind] using sections. *) |
797 | |
798 (** We can check the implementation [nat_rect] as well: *) | |
799 | |
800 Print nat_rect. | |
801 (** %\vspace{-.15in}% [[ | |
802 nat_rect = | |
803 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) => | |
804 fix F (n : nat) : P n := | |
805 match n as n0 return (P n0) with | |
806 | O => f | |
807 | S n0 => f0 n0 (F n0) | |
808 end | |
809 : forall P : nat -> Type, | |
810 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n | |
811 ]] | |
812 | |
813 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. *) | |
814 | 803 |
815 Section nat_ind'. | 804 Section nat_ind'. |
816 (** First, we have the property of natural numbers that we aim to prove. *) | 805 (** First, we have the property of natural numbers that we aim to prove. *) |
817 | 806 |
818 Variable P : nat -> Prop. | 807 Variable P : nat -> Prop. |