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 ============================