comparison src/InductiveTypes.v @ 475:1fd4109f7b31

Batch of changes based on proofreader feedback
author Adam Chlipala <adam@chlipala.net>
date Mon, 22 Oct 2012 14:23:52 -0400
parents 524458532b76
children 31258618ef73
comparison
equal deleted inserted replaced
474:d9e1fb184672 475:1fd4109f7b31
18 18
19 (** %\part{Basic Programming and Proving} 19 (** %\part{Basic Programming and Proving}
20 20
21 \chapter{Introducing Inductive Types}% *) 21 \chapter{Introducing Inductive Types}% *)
22 22
23 (** In a sense, CIC is built from just two relatively straightforward features: function types and inductive types. From this modest foundation, we can prove effectively all of the theorems of math and carry out effectively all program verifications, with enough effort expended. This chapter introduces induction and recursion for functional programming in Coq. Most of our examples reproduce functionality from the Coq standard library, and I have tried to copy the standard library's choices of identifiers, where possible, so many of the definitions here are already available in the default Coq environment. 23 (** The logical foundation of Coq is the Calculus of Inductive Constructions, or CIC. In a sense, CIC is built from just two relatively straightforward features: function types and inductive types. From this modest foundation, we can prove essentially all of the theorems of math and carry out effectively all program verifications, with enough effort expended. This chapter introduces induction and recursion for functional programming in Coq. Most of our examples reproduce functionality from the Coq standard library, and I have tried to copy the standard library's choices of identifiers, where possible, so many of the definitions here are already available in the default Coq environment.
24 24
25 The last chapter took a deep dive into some of the more advanced Coq features, to highlight the unusual approach that I advocate in this book. However, from this point on, we will rewind and go back to basics, presenting the relevant features of Coq in a more bottom-up manner. A useful first step is a discussion of the differences and relationships between proofs and programs in Coq. *) 25 The last chapter took a deep dive into some of the more advanced Coq features, to highlight the unusual approach that I advocate in this book. However, from this point on, we will rewind and go back to basics, presenting the relevant features of Coq in a more bottom-up manner. A useful first step is a discussion of the differences and relationships between proofs and programs in Coq. *)
26 26
27 27
28 (** * Proof Terms *) 28 (** * Proof Terms *)
617 (fun ol : odd_list => forall el : even_list, 617 (fun ol : odd_list => forall el : even_list,
618 olength (oapp ol el) = plus (olength ol) (elength el))); crush. 618 olength (oapp ol el) = plus (olength ol) (elength el))); crush.
619 Qed. 619 Qed.
620 (* end thide *) 620 (* end thide *)
621 621
622 (** 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. *) 622 (** We simply need to specify two predicates, one for each of the mutually inductive types. In general, it is not a good idea to assume that a proof assistant can infer extra predicates, so this way of applying mutual induction is about as straightforward as we may hope for. *)
623 623
624 624
625 (** * Reflexive Types *) 625 (** * Reflexive Types *)
626 626
627 (** 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. *) 627 (** 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. *)
635 (* begin thide *) 635 (* begin thide *)
636 Definition prod' := prod. 636 Definition prod' := prod.
637 (* end thide *) 637 (* end thide *)
638 (* end hide *) 638 (* end hide *)
639 639
640 (** 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). *) 640 (** 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 instances 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). *)
641 641
642 Fixpoint pformulaDenote (f : pformula) : Prop := 642 Fixpoint pformulaDenote (f : pformula) : Prop :=
643 match f with 643 match f with
644 | Truth => True 644 | Truth => True
645 | Falsehood => False 645 | Falsehood => False
923 Inductive nat_tree : Set := 923 Inductive nat_tree : Set :=
924 | NNode' : nat -> list nat_tree -> nat_tree. 924 | NNode' : nat -> list nat_tree -> nat_tree.
925 925
926 (** This is an example of a%\index{nested inductive type}% _nested_ inductive type definition, because we use the type we are defining as an argument to a parameterized type family. Coq will not allow all such definitions; it effectively pretends that we are defining [nat_tree] mutually with a version of [list] specialized to [nat_tree], checking that the resulting expanded definition satisfies the usual rules. For instance, if we replaced [list] with a type family that used its parameter as a function argument, then the definition would be rejected as violating the positivity restriction. 926 (** This is an example of a%\index{nested inductive type}% _nested_ inductive type definition, because we use the type we are defining as an argument to a parameterized type family. Coq will not allow all such definitions; it effectively pretends that we are defining [nat_tree] mutually with a version of [list] specialized to [nat_tree], checking that the resulting expanded definition satisfies the usual rules. For instance, if we replaced [list] with a type family that used its parameter as a function argument, then the definition would be rejected as violating the positivity restriction.
927 927
928 Like we encountered for mutual inductive types, we find that the automatically generated induction principle for [nat_tree] is too weak. *) 928 As we encountered with mutual inductive types, we find that the automatically generated induction principle for [nat_tree] is too weak. *)
929 929
930 (* begin hide *) 930 (* begin hide *)
931 (* begin thide *) 931 (* begin thide *)
932 Check Forall. 932 Check Forall.
933 (* end thide *) 933 (* end thide *)
1019 << 1019 <<
1020 Recursive call to nat_tree_ind' has principal argument equal to "tr" 1020 Recursive call to nat_tree_ind' has principal argument equal to "tr"
1021 instead of rest. 1021 instead of rest.
1022 >> 1022 >>
1023 1023
1024 There is no deep theoretical reason why this program should be rejected; Coq applies incomplete termination-checking heuristics, and it is necessary to learn a few of the most important rules. The term "nested inductive type" hints at the solution to this particular problem. Just like true mutually inductive types require mutually recursive induction principles, nested types require nested recursion. *) 1024 There is no deep theoretical reason why this program should be rejected; Coq applies incomplete termination-checking heuristics, and it is necessary to learn a few of the most important rules. The term "nested inductive type" hints at the solution to this particular problem. Just as mutually inductive types require mutually recursive induction principles, nested types require nested recursion. *)
1025 1025
1026 Fixpoint nat_tree_ind' (tr : nat_tree) : P tr := 1026 Fixpoint nat_tree_ind' (tr : nat_tree) : P tr :=
1027 match tr with 1027 match tr with
1028 | NNode' n ls => NNode'_case n ls 1028 | NNode' n ls => NNode'_case n ls
1029 ((fix list_nat_tree_ind (ls : list nat_tree) : All P ls := 1029 ((fix list_nat_tree_ind (ls : list nat_tree) : All P ls :=
1035 1035
1036 (** We include an anonymous [fix] version of [list_nat_tree_ind] that is literally _nested_ inside the definition of the recursive function corresponding to the inductive definition that had the nested use of [list]. *) 1036 (** We include an anonymous [fix] version of [list_nat_tree_ind] that is literally _nested_ inside the definition of the recursive function corresponding to the inductive definition that had the nested use of [list]. *)
1037 1037
1038 End nat_tree_ind'. 1038 End nat_tree_ind'.
1039 1039
1040 (** We can try our induction principle out by defining some recursive functions on [nat_tree]s and proving a theorem about them. First, we define some helper functions that operate on lists. *) 1040 (** We can try our induction principle out by defining some recursive functions on [nat_tree] and proving a theorem about them. First, we define some helper functions that operate on lists. *)
1041 1041
1042 Section map. 1042 Section map.
1043 Variables T T' : Set. 1043 Variables T T' : Set.
1044 Variable F : T -> T'. 1044 Variable F : T -> T'.
1045 1045