Mercurial > cpdt > repo
comparison src/InductiveTypes.v @ 469:b36876d4611e
Batch of changes based on proofreader feedback
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 26 Sep 2012 16:35:35 -0400 |
parents | 4320c1a967c2 |
children | 0df6dde807ab |
comparison
equal
deleted
inserted
replaced
468:62475ab7570b | 469:b36876d4611e |
---|---|
58 (** %\smallskip{}%No proofs of %\index{Gallina terms!False}%[False] exist in the top-level context, but the implication-as-function analogy gives us an easy way to, for example, show that [False] implies itself. *) | 58 (** %\smallskip{}%No proofs of %\index{Gallina terms!False}%[False] exist in the top-level context, but the implication-as-function analogy gives us an easy way to, for example, show that [False] implies itself. *) |
59 | 59 |
60 Check (fun x : False => x). | 60 Check (fun x : False => x). |
61 (** [: False -> False] *) | 61 (** [: False -> False] *) |
62 | 62 |
63 (** %\smallskip{}%In fact, [False] implies anything, and we can take advantage of this fact with an odd looking [match] expression that has no branches. Since there are no rules for deducing [False], there are no cases to consider! *) | |
64 | |
65 Check (fun x : False => match x with end : True). | |
66 (** [: False -> True] *) | |
67 | |
68 (** %\smallskip{}%Every one of these example programs whose type looks like a logical formula is a%\index{proof term}% _proof term_. We use that name for any Gallina term of a logical type, and we will elaborate shortly on what makes a type logical. | 63 (** %\smallskip{}%Every one of these example programs whose type looks like a logical formula is a%\index{proof term}% _proof term_. We use that name for any Gallina term of a logical type, and we will elaborate shortly on what makes a type logical. |
69 | 64 |
70 In the rest of this chapter, we will introduce different ways of defining types. Every example type can be interpreted alternatively as a type of programs or %\index{proposition}%propositions (i.e., formulas or theorem statements). | 65 In the rest of this chapter, we will introduce different ways of defining types. Every example type can be interpreted alternatively as a type of programs or proofs. |
71 | 66 |
72 One of the first types we introduce will be [bool], with constructors [true] and [false]. Newcomers to Coq often wonder about the distinction between [True] and [true] and the distinction between [False] and [false]. One glib answer is that [True] and [False] are types, but [true] and [false] are not. A more useful answer is that Coq's metatheory guarantees that any term of type [bool] _evaluates_ to either [true] or [false]. This means that we have an _algorithm_ for answering any question phrased as an expression of type [bool]. Conversely, most propositions do not evaluate to [True] or [False]; the language of inductively defined propositions is much richer than that. We ought to be glad that we have no algorithm for deciding mathematical truth, since otherwise it would be clear that we could not formalize undecidable properties, like most any properties of general-purpose programs. *) | 67 One of the first types we introduce will be [bool], with constructors [true] and [false]. Newcomers to Coq often wonder about the distinction between [True] and [true] and the distinction between [False] and [false]. One glib answer is that [True] and [False] are types, but [true] and [false] are not. A more useful answer is that Coq's metatheory guarantees that any term of type [bool] _evaluates_ to either [true] or [false]. This means that we have an _algorithm_ for answering any question phrased as an expression of type [bool]. Conversely, most propositions do not evaluate to [True] or [False]; the language of inductively defined propositions is much richer than that. We ought to be glad that we have no algorithm for deciding mathematical truth, since otherwise it would be clear that we could not formalize undecidable properties, like almost any interesting property of general-purpose programs. *) |
73 | 68 |
74 | 69 |
75 (** * Enumerations *) | 70 (** * Enumerations *) |
76 | 71 |
77 (** Coq inductive types generalize the %\index{algebraic datatypes}%algebraic datatypes found in %\index{Haskell}%Haskell and %\index{ML}%ML. Confusingly enough, inductive types also generalize %\index{generalized algebraic datatypes}%generalized algebraic datatypes (GADTs), by adding the possibility for type dependency. Even so, it is worth backing up from the examples of the last chapter and going over basic, algebraic datatype uses of inductive datatypes, because the chance to prove things about the values of these types adds new wrinkles beyond usual practice in Haskell and ML. | 72 (** Coq inductive types generalize the %\index{algebraic datatypes}%algebraic datatypes found in %\index{Haskell}%Haskell and %\index{ML}%ML. Confusingly enough, inductive types also generalize %\index{generalized algebraic datatypes}%generalized algebraic datatypes (GADTs), by adding the possibility for type dependency. Even so, it is worth backing up from the examples of the last chapter and going over basic, algebraic datatype uses of inductive datatypes, because the chance to prove things about the values of these types adds new wrinkles beyond usual practice in Haskell and ML. |
251 match n with | 246 match n with |
252 | O => O | 247 | O => O |
253 | S n' => n' | 248 | S n' => n' |
254 end. | 249 end. |
255 | 250 |
256 (** We can prove theorems by case analysis: *) | 251 (** We can prove theorems by case analysis with [destruct] as for simpler inductive types, but we can also now get into genuine inductive theorems. First, we will need a recursive function, to make things interesting.%\index{Gallina terms!plus}% *) |
257 | |
258 Theorem S_isZero : forall n : nat, isZero (pred (S (S n))) = false. | |
259 (* begin thide *) | |
260 destruct n; reflexivity. | |
261 Qed. | |
262 (* end thide *) | |
263 | |
264 (** We can also now get into genuine inductive theorems. First, we will need a recursive function, to make things interesting.%\index{Gallina terms!plus}% *) | |
265 | 252 |
266 Fixpoint plus (n m : nat) : nat := | 253 Fixpoint plus (n m : nat) : nat := |
267 match n with | 254 match n with |
268 | O => m | 255 | O => m |
269 | S n' => S (plus n' m) | 256 | S n' => S (plus n' m) |
285 | 272 |
286 (** Our first subgoal is [plus O O = O], which _is_ trivial by computation. *) | 273 (** Our first subgoal is [plus O O = O], which _is_ trivial by computation. *) |
287 | 274 |
288 reflexivity. | 275 reflexivity. |
289 | 276 |
290 (** Our second subgoal is more work and also demonstrates our first inductive hypothesis. | 277 (** Our second subgoal requires more work and also demonstrates our first inductive hypothesis. |
291 | 278 |
292 [[ | 279 [[ |
293 n : nat | 280 n : nat |
294 IHn : plus n O = n | 281 IHn : plus n O = n |
295 ============================ | 282 ============================ |
487 induction ls1; crush. | 474 induction ls1; crush. |
488 Qed. | 475 Qed. |
489 (* end thide *) | 476 (* end thide *) |
490 End list. | 477 End list. |
491 | 478 |
492 (* begin hide *) | |
493 Implicit Arguments Nil [T]. | 479 Implicit Arguments Nil [T]. |
494 (* end hide *) | 480 |
495 | 481 (** After we end the section, the [Variable]s we used are added as extra function parameters for each defined identifier, as needed. With an [Implicit Arguments]%~\index{Vernacular commands!Implicit Arguments}% command, we ask that [T] be inferred when we use [Nil]; Coq's heuristics already decided to apply a similar policy to [Cons], because of the [Set Implicit Arguments]%~\index{Vernacular commands!Set Implicit Arguments}% command elided at the beginning of this chapter. We verify that our definitions have been saved properly using the [Print] command, a cousin of [Check] which shows the definition of a symbol, rather than just its type. *) |
496 (** After we end the section, the [Variable]s we used are added as extra function parameters for each defined identifier, as needed. We verify that this has happened using the [Print] command, a cousin of [Check] which shows the definition of a symbol, rather than just its type. *) | |
497 | 482 |
498 Print list. | 483 Print list. |
499 (** %\vspace{-.15in}% [[ | 484 (** %\vspace{-.15in}% [[ |
500 Inductive list (T : Set) : Set := | 485 Inductive list (T : Set) : Set := |
501 Nil : list T | Cons : T -> list T -> list T | 486 Nil : list T | Cons : T -> list T -> list T |
625 (** We simply need to specify two predicates, one for each of the mutually inductive types. In general, it would not be a good idea to assume that a proof assistant could infer extra predicates, so this way of applying mutual induction is about as straightforward as we could hope for. *) | 610 (** We simply need to specify two predicates, one for each of the mutually inductive types. In general, it would not be a good idea to assume that a proof assistant could infer extra predicates, so this way of applying mutual induction is about as straightforward as we could hope for. *) |
626 | 611 |
627 | 612 |
628 (** * Reflexive Types *) | 613 (** * Reflexive Types *) |
629 | 614 |
630 (** A kind of inductive type called a _reflexive type_ is defined in terms of functions that have the type being defined as their range. One very useful class of examples is in modeling variable binders. Our example will be an encoding of the syntax of first-order logic. Since the idea of syntactic encodings of logic may require a bit of acclimation, let us first consider a simpler formula type for a subset of propositional logic. *) | 615 (** A kind of inductive type called a _reflexive type_ includes at least one constructor that takes as an argument _a function returning the same type we are defining_. One very useful class of examples is in modeling variable binders. Our example will be an encoding of the syntax of first-order logic. Since the idea of syntactic encodings of logic may require a bit of acclimation, let us first consider a simpler formula type for a subset of propositional logic. We are not yet using a reflexive type, but later we will extend the example reflexively. *) |
631 | 616 |
632 Inductive pformula : Set := | 617 Inductive pformula : Set := |
633 | Truth : pformula | 618 | Truth : pformula |
634 | Falsehood : pformula | 619 | Falsehood : pformula |
635 | Conjunction : pformula -> pformula -> pformula. | 620 | Conjunction : pformula -> pformula -> pformula. |
702 | 687 |
703 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. | 688 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. |
704 | 689 |
705 %\medskip% | 690 %\medskip% |
706 | 691 |
707 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. | 692 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; only some of them are legal. |
708 | 693 |
709 Given our last example of an inductive type, many readers are probably eager to try encoding the syntax of %\index{lambda calculus}%lambda calculus. Indeed, the function-based representation technique that we just used, called%\index{higher-order abstract syntax}\index{HOAS|see{higher-order abstract syntax}}% _higher-order abstract syntax_ (HOAS)%~\cite{HOAS}%, is the representation of choice for lambda calculi in %\index{Twelf}%Twelf and in many applications implemented in Haskell and ML. Let us try to import that choice to Coq: *) | 694 Given our last example of an inductive type, many readers are probably eager to try encoding the syntax of %\index{lambda calculus}%lambda calculus. Indeed, the function-based representation technique that we just used, called%\index{higher-order abstract syntax}\index{HOAS|see{higher-order abstract syntax}}% _higher-order abstract syntax_ (HOAS)%~\cite{HOAS}%, is the representation of choice for lambda calculi in %\index{Twelf}%Twelf and in many applications implemented in Haskell and ML. Let us try to import that choice to Coq: *) |
710 (* begin hide *) | 695 (* begin hide *) |
711 (* begin thide *) | 696 (* begin thide *) |
712 Inductive term : Set := App | Abs. | 697 Inductive term : Set := App | Abs. |
798 %\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. | 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. |
799 | 784 |
800 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) | 785 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) |
801 | 786 |
802 Definition unit_rect' (P : unit -> Type) (f : P tt) (u : unit) := | 787 Definition unit_rect' (P : unit -> Type) (f : P tt) (u : unit) := |
803 match u with | 788 match u return P u with |
804 | tt => f | 789 | tt => f |
805 end. | 790 end. |
806 | 791 |
807 (* begin hide *) | 792 (* begin hide *) |
808 (* begin thide *) | 793 (* begin thide *) |
809 Definition foo := nat_rect. | 794 Definition foo := nat_rect. |
810 (* end thide *) | 795 (* end thide *) |
811 (* end hide *) | 796 (* end hide *) |
812 | 797 |
813 (** We rely on Coq's heuristics for inferring [match] annotations, which are not consulted in the pretty-printing of terms. | 798 (** We can check the implementation [nat_rect] as well: *) |
814 | |
815 We can check the implementation [nat_rect] as well: *) | |
816 | 799 |
817 Print nat_rect. | 800 Print nat_rect. |
818 (** %\vspace{-.15in}% [[ | 801 (** %\vspace{-.15in}% [[ |
819 nat_rect = | 802 nat_rect = |
820 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) => | 803 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) => |