comparison src/InductiveTypes.v @ 317:50db9a6e2742

Finished pass over InductiveTypes
author Adam Chlipala <adam@chlipala.net>
date Mon, 12 Sep 2011 11:21:27 -0400
parents 2aaff91f5258
children 70e51e8cfce7
comparison
equal deleted inserted replaced
316:2aaff91f5258 317:50db9a6e2742
65 Check (fun x : False => match x with end : True). 65 Check (fun x : False => match x with end : True).
66 (** [: False -> True] *) 66 (** [: False -> True] *)
67 67
68 (** Every one of these example programs whose type looks like a logical formula is a %\index{proof term}\emph{%#<i>#proof term#</i>#%}%. We use that name for any Gallina term of a logical type, and we will elaborate shortly on what makes a type logical. 68 (** Every one of these example programs whose type looks like a logical formula is a %\index{proof term}\emph{%#<i>#proof term#</i>#%}%. We use that name for any Gallina term of a logical type, and we will elaborate shortly on what makes a type logical.
69 69
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). *) 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).
71
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] %\emph{%#<i>#evaluates#</i>#%}% to either [true] or [false]. This means that we have an %\emph{%#<i>#algorithm#</i>#%}% 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. *)
71 73
72 74
73 (** * Enumerations *) 75 (** * Enumerations *)
74 76
75 (** 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. 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.
141 (* begin thide *) 143 (* begin thide *)
142 destruct 1. 144 destruct 1.
143 Qed. 145 Qed.
144 (* end thide *) 146 (* end thide *)
145 147
146 (** Because [Empty_set] has no elements, the fact of having an element of this type implies anything. We use [destruct 1] instead of [destruct x] in the proof because unused quantified variables are relegated to being referred to by number. (There is a good reason for this, related to the unity of quantifiers and implication. An implication is just a quantification over a proof, where the quantified variable is never used. It generally makes more sense to refer to implication hypotheses by number than by name, and Coq treats our quantifier over an unused variable as an implication in determining the proper behavior.) 148 (** Because [Empty_set] has no elements, the fact of having an element of this type implies anything. We use [destruct 1] instead of [destruct x] in the proof because unused quantified variables are relegated to being referred to by number. (There is a good reason for this, related to the unity of quantifiers and implication. At least within Coq's logical foundation of %\index{constructive logic}%constructive logic, which we elaborate on more in the next chapter, an implication is just a quantification over a proof, where the quantified variable is never used. It generally makes more sense to refer to implication hypotheses by number than by name, and Coq treats our quantifier over an unused variable as an implication in determining the proper behavior.)
147 149
148 We can see the induction principle that made this proof so easy: *) 150 We can see the induction principle that made this proof so easy: *)
149 151
150 Check Empty_set_ind. 152 Check Empty_set_ind.
151 (** [Empty_set_ind : forall (][P : Empty_set -> Prop) (e : Empty_set), P e] *) 153 (** [Empty_set_ind : forall (][P : Empty_set -> Prop) (e : Empty_set), P e] *)
172 match b with 174 match b with
173 | true => false 175 | true => false
174 | false => true 176 | false => true
175 end. 177 end.
176 178
177 (** An alternative definition desugars to the above: *) 179 (** An alternative definition desugars to the above, thanks to an %\index{Gallina terms!if}%[if] notation overloaded to work with any inductive type that has exactly two constructors: *)
178 180
179 Definition negb' (b : bool) : bool := 181 Definition negb' (b : bool) : bool :=
180 if b then false else true. 182 if b then false else true.
181 183
182 (** We might want to prove that [negb] is its own inverse operation. *) 184 (** We might want to prove that [negb] is its own inverse operation. *)
647 Inductive pformula : Set := 649 Inductive pformula : Set :=
648 | Truth : pformula 650 | Truth : pformula
649 | Falsehood : pformula 651 | Falsehood : pformula
650 | Conjunction : pformula -> pformula -> pformula. 652 | Conjunction : pformula -> pformula -> pformula.
651 653
652 (** A key distinction here is between, for instance, the %\emph{%#<i>#syntax#</i>#%}% [Truth] and its %\emph{%#<i>#semantics#</i>#%}% [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!conj}%[conj] from the standard library. The family [conj] implements conjunction (i.e., %``%#"#and#"#%''%), 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). *) 654 (** A key distinction here is between, for instance, the %\emph{%#<i>#syntax#</i>#%}% [Truth] and its %\emph{%#<i>#semantics#</i>#%}% [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). *)
653 655
654 Fixpoint pformulaDenote (f : pformula) : Prop := 656 Fixpoint pformulaDenote (f : pformula) : Prop :=
655 match f with 657 match f with
656 | Truth => True 658 | Truth => True
657 | Falsehood => False 659 | Falsehood => False
745 %\index{termination checking}%For Coq, however, this would be a disaster. The possibility of writing such a function would destroy all our confidence that proving a theorem means anything. Since Coq combines programs and proofs in one language, we would be able to prove every theorem with an infinite loop. 747 %\index{termination checking}%For Coq, however, this would be a disaster. The possibility of writing such a function would destroy all our confidence that proving a theorem means anything. Since Coq combines programs and proofs in one language, we would be able to prove every theorem with an infinite loop.
746 748
747 Nonetheless, the basic insight of HOAS is a very useful one, and there are ways to realize most benefits of HOAS in Coq. We will study a particular technique of this kind in the later chapters on programming language syntax and semantics. *) 749 Nonetheless, the basic insight of HOAS is a very useful one, and there are ways to realize most benefits of HOAS in Coq. We will study a particular technique of this kind in the later chapters on programming language syntax and semantics. *)
748 750
749 751
750 (** * An Interlude on Proof Terms *) 752 (** * An Interlude on Induction Principles *)
751 753
752 (** 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 induction principles we have used. *) 754 (** 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. *)
753 755
756 (* begin hide *)
754 Print unit_ind. 757 Print unit_ind.
755 (** %\vspace{-.15in}% [[ 758 (* end hide *)
759 (** %\noindent%[Print] [unit_ind.] *)
760 (** [[
756 unit_ind = 761 unit_ind =
757 fun P : unit -> Prop => unit_rect P 762 fun P : unit -> Prop => unit_rect P
758 : forall P : unit -> Prop, P tt -> forall u : unit, P u 763 : forall P : unit -> Prop, P tt -> forall u : unit, P u
759 764
760 ]] 765 ]]
761 766
762 We see that this induction principle is defined in terms of a more general principle, [unit_rect]. *) 767 We see that this induction principle is defined in terms of a more general principle, [unit_rect]. The %\texttt{%#<tt>#rec#</tt>#%}% stands for %``%#"#recursion principle,#"#%''% and the %\texttt{%#<tt>#t#</tt>#%}% at the end stands for [Type]. *)
763 768
764 Check unit_rect. 769 Check unit_rect.
765 (** %\vspace{-.15in}% [[ 770 (** %\vspace{-.15in}% [[
766 unit_rect 771 unit_rect
767 : forall P : unit -> Type, P tt -> forall u : unit, P u 772 : forall P : unit -> Type, P tt -> forall u : unit, P u
768 773
769 ]] 774 ]]
770 775
771 [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: *) 776 [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: *)
772 777
778 (* begin hide *)
773 Print unit_rec. 779 Print unit_rec.
774 (** %\vspace{-.15in}% [[ 780 (* end hide *)
781 (** %\noindent%[Print] [unit_rec.] *)
782 (** [[
775 unit_rec = 783 unit_rec =
776 fun P : unit -> Set => unit_rect P 784 fun P : unit -> Set => unit_rect P
777 : forall P : unit -> Set, P tt -> forall u : unit, P u 785 : forall P : unit -> Set, P tt -> forall u : unit, P u
778 786
779 ]] 787 ]]
780 788
781 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 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: *) 789 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: *)
782 790
783 Definition always_O (u : unit) : nat := 791 Definition always_O (u : unit) : nat :=
784 match u with 792 match u with
785 | tt => O 793 | tt => O
786 end. 794 end.
788 Definition always_O' (u : unit) : nat := 796 Definition always_O' (u : unit) : nat :=
789 unit_rec (fun _ : unit => nat) O u. 797 unit_rec (fun _ : unit => nat) O u.
790 798
791 (** 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. *) 799 (** 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. *)
792 800
801 (* begin hide *)
793 Print unit_rect. 802 Print unit_rect.
794 (** %\vspace{-.15in}% [[ 803 (* end hide *)
804 (** %\noindent%[Print] [unit_rect.] *)
805 (** [[
795 unit_rect = 806 unit_rect =
796 fun (P : unit -> Type) (f : P tt) (u : unit) => 807 fun (P : unit -> Type) (f : P tt) (u : unit) =>
797 match u as u0 return (P u0) with 808 match u as u0 return (P u0) with
798 | tt => f 809 | tt => f
799 end 810 end
800 : forall P : unit -> Type, P tt -> forall u : unit, P u 811 : forall P : unit -> Type, P tt -> forall u : unit, P u
801 812
802 ]] 813 ]]
803 814
804 The only new feature we see is an [as] clause for a [match], which is used in concert with the [return] clause that we saw in the introduction. Since the type of the [match] is dependent on the value of the object being analyzed, we must give that object a name so that we can refer to it in the [return] clause. 815 The only new wrinkle here is the annotations on the [match] expression. This is a %\index{dependent pattern matching}\emph{%#<i>#dependently typed#</i>#%}% pattern match, because the %\emph{%#<i>#type#</i>#%}% of the expression depends on the %\emph{%#<i>#value#</i>#%}% 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.
816
817 %\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.
805 818
806 To prove that [unit_rect] is nothing special, we can reimplement it manually. *) 819 To prove that [unit_rect] is nothing special, we can reimplement it manually. *)
807 820
808 Definition unit_rect' (P : unit -> Type) (f : P tt) (u : unit) := 821 Definition unit_rect' (P : unit -> Type) (f : P tt) (u : unit) :=
809 match u with 822 match u with
810 | tt => f 823 | tt => f
811 end. 824 end.
812 825
813 (** We rely on Coq's heuristics for inferring [match] annotations. 826 (** We rely on Coq's heuristics for inferring [match] annotations, which are not consulted in the pretty-printing of terms.
814 827
815 We can check the implementation of [nat_rect] as well: *) 828 We can check the implementation of %\coqdocdefinition{%#<tt>#nat_rect#</tt>#%}% as well: *)
816 829
830 (* begin hide *)
817 Print nat_rect. 831 Print nat_rect.
818 (** %\vspace{-.15in}% [[ 832 (* end hide *)
819 nat_rect = 833 (** %\noindent%[Print] %\coqdocdefinition{%#<tt>#nat_rect#</tt>#%}%[.] *)
834
835 (** %\hspace{-.05in}\coqdocdefinition{%#<tt>#nat_rect#</tt>#%}% [=] *)
836 (** %\vspace{-.05in}% [[
820 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) => 837 fun (P : nat -> Type) (f : P O) (f0 : forall n : nat, P n -> P (S n)) =>
821 fix F (n : nat) : P n := 838 fix F (n : nat) : P n :=
822 match n as n0 return (P n0) with 839 match n as n0 return (P n0) with
823 | O => f 840 | O => f
824 | S n0 => f0 n0 (F n0) 841 | S n0 => f0 n0 (F n0)
825 end 842 end
826 : forall P : nat -> Type, 843 : forall P : nat -> Type,
827 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n 844 P O -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n
828 ]] 845 ]]
829 846
830 Now we have an actual recursive definition. [fix] expressions are an anonymous form 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. *) 847 Now we have an actual recursive definition. %\index{Gallina terms!fix}%[fix] expressions are an anonymous form 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 %\coqdocdefinition{%#<tt>#nat_rect#</tt>#%}% better by reimplementing [nat_ind] using sections. *)
831 848
832 Section nat_ind'. 849 Section nat_ind'.
833 (** First, we have the property of natural numbers that we aim to prove. *) 850 (** First, we have the property of natural numbers that we aim to prove. *)
834 851
835 Variable P : nat -> Prop. 852 Variable P : nat -> Prop.
836 853
837 (** Then we require a proof of the [O] case. *) 854 (** Then we require a proof of the [O] case, which we declare with the command %\index{Vernacular commands!Hypothesis}%[Hypothesis], which is a synonym for [Variable] that, by convention, is used for variables whose types are propositions. *)
838 855
839 Hypothesis O_case : P O. 856 Hypothesis O_case : P O.
840 857
841 (** Next is a proof of the [S] case, which may assume an inductive hypothesis. *) 858 (** Next is a proof of the [S] case, which may assume an inductive hypothesis. *)
842 859
843 Hypothesis S_case : forall n : nat, P n -> P (S n). 860 Hypothesis S_case : forall n : nat, P n -> P (S n).
844 861
845 (** Finally, we define a recursive function to tie the pieces together. *) 862 (** Finally, we define a recursive function to tie the pieces together. *)
846 863
847 Fixpoint nat_ind' (n : nat) : P n := 864 Fixpoint nat_ind' (n : nat) : P n :=
848 match n with 865 match n with
849 | O => O_case 866 | O => O_case
850 | S n' => S_case (nat_ind' n') 867 | S n' => S_case (nat_ind' n')
851 end. 868 end.
852 End nat_ind'. 869 End nat_ind'.
853 870
854 (** Closing the section adds the [Variable]s and [Hypothesis]es as new [fun]-bound arguments to [nat_ind'], and, modulo the use of [Prop] instead of [Type], we end up with the exact same definition that was generated automatically for [nat_rect]. 871 (** Closing the section adds the [Variable]s and [Hypothesis]es as new [fun]-bound arguments to [nat_ind'], and, modulo the use of [Prop] instead of [Type], we end up with the exact same definition that was generated automatically for %\coqdocdefinition{%#<tt>#nat_rect#</tt>#%}%.
855 872
856 %\medskip% 873 %\medskip%
857 874
858 We can also examine the definition of [even_list_mut], which we generated with [Scheme] for a mutually-recursive type. *) 875 We can also examine the definition of [even_list_mut], which we generated with [Scheme] for a mutually recursive type. *)
859 876
860 Print even_list_mut. 877 (* begin hide *)
861 (** %\vspace{-.15in}% [[ 878 Print even_list_mut.
862 even_list_mut = 879 (* end hide *)
863 fun (P : even_list -> Prop) (P0 : odd_list -> Prop) 880 (** %\noindent%[Print] %\coqdocdefinition{%#<tt>#even_list_mut#</tt>#%}%[.] *)
864 (f : P ENil) (f0 : forall (n : nat) (o : odd_list), P0 o -> P (ECons n o)) 881 (** [[
865 (f1 : forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) => 882 even_list_mut =
866 fix F (e : even_list) : P e := 883 fun (P : even_list -> Prop) (P0 : odd_list -> Prop)
867 match e as e0 return (P e0) with 884 (f : P ENil) (f0 : forall (n : nat) (o : odd_list), P0 o -> P (ECons n o))
868 | ENil => f 885 (f1 : forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) =>
869 | ECons n o => f0 n o (F0 o) 886 fix F (e : even_list) : P e :=
870 end 887 match e as e0 return (P e0) with
871 with F0 (o : odd_list) : P0 o := 888 | ENil => f
872 match o as o0 return (P0 o0) with 889 | ECons n o => f0 n o (F0 o)
873 | OCons n e => f1 n e (F e) 890 end
874 end 891 with F0 (o : odd_list) : P0 o :=
875 for F 892 match o as o0 return (P0 o0) with
876 : forall (P : even_list -> Prop) (P0 : odd_list -> Prop), 893 | OCons n e => f1 n e (F e)
877 P ENil -> 894 end
878 (forall (n : nat) (o : odd_list), P0 o -> P (ECons n o)) -> 895 for F
879 (forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) -> 896 : forall (P : even_list -> Prop) (P0 : odd_list -> Prop),
880 forall e : even_list, P e 897 P ENil ->
881 898 (forall (n : nat) (o : odd_list), P0 o -> P (ECons n o)) ->
882 ]] 899 (forall (n : nat) (e : even_list), P e -> P0 (OCons n e)) ->
883 900 forall e : even_list, P e
884 We see a mutually-recursive [fix], with the different functions separated by [with] in the same way that they would be separated by [and] in ML. A final [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. *) 901
885 902 ]]
886 Section even_list_mut'. 903
887 (** First, we need the properties that we are proving. *) 904 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 %\texttt{%#<tt>#and#</tt>#%}% 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. *)
888 905
889 Variable Peven : even_list -> Prop. 906 Section even_list_mut'.
890 Variable Podd : odd_list -> Prop. 907 (** First, we need the properties that we are proving. *)
891 908
892 (** Next, we need proofs of the three cases. *) 909 Variable Peven : even_list -> Prop.
893 910 Variable Podd : odd_list -> Prop.
894 Hypothesis ENil_case : Peven ENil. 911
895 Hypothesis ECons_case : forall (n : nat) (o : odd_list), Podd o -> Peven (ECons n o). 912 (** Next, we need proofs of the three cases. *)
896 Hypothesis OCons_case : forall (n : nat) (e : even_list), Peven e -> Podd (OCons n e). 913
897 914 Hypothesis ENil_case : Peven ENil.
898 (** Finally, we define the recursive functions. *) 915 Hypothesis ECons_case : forall (n : nat) (o : odd_list), Podd o -> Peven (ECons n o).
899 916 Hypothesis OCons_case : forall (n : nat) (e : even_list), Peven e -> Podd (OCons n e).
900 Fixpoint even_list_mut' (e : even_list) : Peven e := 917
901 match e with 918 (** Finally, we define the recursive functions. *)
902 | ENil => ENil_case 919
903 | ECons n o => ECons_case n (odd_list_mut' o) 920 Fixpoint even_list_mut' (e : even_list) : Peven e :=
904 end 921 match e with
905 with odd_list_mut' (o : odd_list) : Podd o := 922 | ENil => ENil_case
906 match o with 923 | ECons n o => ECons_case n (odd_list_mut' o)
907 | OCons n e => OCons_case n (even_list_mut' e) 924 end
908 end. 925 with odd_list_mut' (o : odd_list) : Podd o :=
926 match o with
927 | OCons n e => OCons_case n (even_list_mut' e)
928 end.
909 End even_list_mut'. 929 End even_list_mut'.
910 930
911 (** Even induction principles for reflexive types are easy to implement directly. For our [formula] type, we can use a recursive definition much like those we wrote above. *) 931 (** Even induction principles for reflexive types are easy to implement directly. For our [formula] type, we can use a recursive definition much like those we wrote above. *)
912 932
913 Section formula_ind'. 933 Section formula_ind'.
924 | And f1 f2 => And_case (formula_ind' f1) (formula_ind' f2) 944 | And f1 f2 => And_case (formula_ind' f1) (formula_ind' f2)
925 | Forall f' => Forall_case f' (fun n => formula_ind' (f' n)) 945 | Forall f' => Forall_case f' (fun n => formula_ind' (f' n))
926 end. 946 end.
927 End formula_ind'. 947 End formula_ind'.
928 948
949 (** It is apparent that induction principle implementations involve some tedium but not terribly much creativity. *)
950
929 951
930 (** * Nested Inductive Types *) 952 (** * Nested Inductive Types *)
931 953
932 (** Suppose we want to extend our earlier type of binary trees to trees with arbitrary finite branching. We can use lists to give a simple definition. *) 954 (** Suppose we want to extend our earlier type of binary trees to trees with arbitrary finite branching. We can use lists to give a simple definition. *)
933 955
934 Inductive nat_tree : Set := 956 Inductive nat_tree : Set :=
935 | NLeaf' : nat_tree 957 | NLeaf' : nat_tree
936 | NNode' : nat -> list nat_tree -> nat_tree. 958 | NNode' : nat -> list nat_tree -> nat_tree.
937 959
938 (** This is an example of a %\textit{%#<i>#nested#</i>#%}% inductive type definition, because we use the type we are defining as an argument to a parametrized 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. 960 (** This is an example of a %\index{nested inductive type}\textit{%#<i>#nested#</i>#%}% inductive type definition, because we use the type we are defining as an argument to a parametrized 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.
939 961
940 Like we encountered for mutual inductive types, we find that the automatically-generated induction principle for [nat_tree] is too weak. *) 962 Like we encountered for mutual inductive types, we find that the automatically generated induction principle for [nat_tree] is too weak. *)
941 963
942 Check nat_tree_ind. 964 Check nat_tree_ind.
943 (** %\vspace{-.15in}% [[ 965 (** %\vspace{-.15in}% [[
944 nat_tree_ind 966 nat_tree_ind
945 : forall P : nat_tree -> Prop, 967 : forall P : nat_tree -> Prop,
947 (forall (n : nat) (l : list nat_tree), P (NNode' n l)) -> 969 (forall (n : nat) (l : list nat_tree), P (NNode' n l)) ->
948 forall n : nat_tree, P n 970 forall n : nat_tree, P n
949 971
950 ]] 972 ]]
951 973
952 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 to different type families. Now that we know how to implement induction principles manually, we are in a position to apply just such creativity to this problem. 974 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.
953 975
954 First, we will need an auxiliary definition, characterizing what it means for a property to hold of every element of a list. *) 976 First, we will need an auxiliary definition, characterizing what it means for a property to hold of every element of a list. *)
955 977
956 Section All. 978 Section All.
957 Variable T : Set. 979 Variable T : Set.
962 | Nil => True 984 | Nil => True
963 | Cons h t => P h /\ All t 985 | Cons h t => P h /\ All t
964 end. 986 end.
965 End All. 987 End All.
966 988
967 (** It will be useful to look at the definitions of [True] and [/\], since we will want to write manual proofs of them below. *) 989 (** It will be useful to review the definitions of [True] and [/\], since we will want to write manual proofs of them below. *)
968 990
991 (* begin hide *)
969 Print True. 992 Print True.
970 (** %\vspace{-.15in}% [[ 993 (* end hide *)
994 (** %\noindent%[Print] %\coqdocinductive{%#<tt>#True#</tt>#%}%[.] *)
995 (** [[
971 Inductive True : Prop := I : True 996 Inductive True : Prop := I : True
972
973 ]] 997 ]]
974 998
975 That is, [True] is a proposition with exactly one proof, [I], which we may always supply trivially. 999 That is, [True] is a proposition with exactly one proof, [I], which we may always supply trivially.
976 1000
977 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 [Locate] command. *) 1001 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}\coqdockw{%#<tt>#Locate#</tt>#%}% command, whose argument may be a parsing token.%\index{Gallina terms!and}% *)
978 1002
1003 (* begin hide *)
979 Locate "/\". 1004 Locate "/\".
980 (** %\vspace{-.15in}% [[ 1005 (* end hide *)
981 Notation Scope 1006 (** %\noindent \coqdockw{Locate}%#<tt>Locate</tt># ["/\".] *)
982 "A /\ B" := and A B : type_scope 1007 (** [[
983 (default interpretation) 1008 "A /\ B" := and A B : type_scope (default interpretation)
984 ]] 1009 ]]
985 *) 1010 *)
986 1011
1012 (* begin hide *)
987 Print and. 1013 Print and.
988 (** %\vspace{-.15in}% [[ 1014 (* end hide *)
1015 (** %\noindent%[Print] %\coqdocinductive{%#<tt>#and#</tt>#%}%[.] *)
1016 (** [[
989 Inductive and (A : Prop) (B : Prop) : Prop := conj : A -> B -> A /\ B 1017 Inductive and (A : Prop) (B : Prop) : Prop := conj : A -> B -> A /\ B
1018 ]]
1019 %\vspace{-.1in}%
1020 <<
990 For conj: Arguments A, B are implicit 1021 For conj: Arguments A, B are implicit
991 For and: Argument scopes are [type_scope type_scope] 1022 >>
992 For conj: Argument scopes are [type_scope type_scope _ _] 1023
993 1024 In addition to the definition of %\coqdocinductive{%#<tt>#and#</tt>#%}% itself, we get information on %\index{implicit arguments}%implicit arguments (and some other information that we omit here). The implicit argument information tells us that we build a proof of a conjunction by calling the constructor [conj] on proofs of the conjuncts, with no need to include the types of those proofs as explicit arguments.
994 ]]
995
996 In addition to the definition of [and] itself, we get information on implicit arguments and parsing rules for [and] and its constructor [conj]. We will ignore the parsing information for now. The implicit argument information tells us that we build a proof of a conjunction by calling the constructor [conj] on proofs of the conjuncts, with no need to include the types of those proofs as explicit arguments.
997 1025
998 %\medskip% 1026 %\medskip%
999 1027
1000 Now we create a section for our induction principle, following the same basic plan as in the last section of this chapter. *) 1028 Now we create a section for our induction principle, following the same basic plan as in the last section of this chapter. *)
1001 1029
1021 | Cons tr rest => conj (nat_tree_ind' tr) (list_nat_tree_ind rest) 1049 | Cons tr rest => conj (nat_tree_ind' tr) (list_nat_tree_ind rest)
1022 end. 1050 end.
1023 1051
1024 ]] 1052 ]]
1025 1053
1026 Coq rejects this definition, saying %``%#"#Recursive call to nat_tree_ind' has principal argument equal to "tr" instead of rest.#"#%''% 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. *) 1054 Coq rejects this definition, saying
1055 <<
1056 Recursive call to nat_tree_ind' has principal argument equal to "tr"
1057 instead of rest.
1058 >>
1059
1060 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. *)
1027 1061
1028 Fixpoint nat_tree_ind' (tr : nat_tree) : P tr := 1062 Fixpoint nat_tree_ind' (tr : nat_tree) : P tr :=
1029 match tr with 1063 match tr with
1030 | NLeaf' => NLeaf'_case 1064 | NLeaf' => NLeaf'_case
1031 | NNode' n ls => NNode'_case n ls 1065 | NNode' n ls => NNode'_case n ls
1042 1076
1043 (** 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. *) 1077 (** 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. *)
1044 1078
1045 Section map. 1079 Section map.
1046 Variables T T' : Set. 1080 Variables T T' : Set.
1047 Variable f : T -> T'. 1081 Variable F : T -> T'.
1048 1082
1049 Fixpoint map (ls : list T) : list T' := 1083 Fixpoint map (ls : list T) : list T' :=
1050 match ls with 1084 match ls with
1051 | Nil => Nil 1085 | Nil => Nil
1052 | Cons h t => Cons (f h) (map t) 1086 | Cons h t => Cons (F h) (map t)
1053 end. 1087 end.
1054 End map. 1088 End map.
1055 1089
1056 Fixpoint sum (ls : list nat) : nat := 1090 Fixpoint sum (ls : list nat) : nat :=
1057 match ls with 1091 match ls with
1088 (** Now we begin the proof of the theorem, adding the lemma [plus_S] as a hint. *) 1122 (** Now we begin the proof of the theorem, adding the lemma [plus_S] as a hint. *)
1089 1123
1090 Theorem ntsize_ntsplice : forall tr1 tr2 : nat_tree, ntsize (ntsplice tr1 tr2) 1124 Theorem ntsize_ntsplice : forall tr1 tr2 : nat_tree, ntsize (ntsplice tr1 tr2)
1091 = plus (ntsize tr2) (ntsize tr1). 1125 = plus (ntsize tr2) (ntsize tr1).
1092 (* begin thide *) 1126 (* begin thide *)
1127 (* begin hide *)
1093 Hint Rewrite plus_S : cpdt. 1128 Hint Rewrite plus_S : cpdt.
1094 1129 (* end hide *)
1095 (** We know that the standard induction principle is insufficient for the task, so we need to provide a [using] clause for the [induction] tactic to specify our alternate principle. *) 1130 (** [Hint] %\coqdockw{%#<tt>#Rewrite#</tt>#%}% [plus_S : cpdt.] *)
1131
1132 (** We know that the standard induction principle is insufficient for the task, so we need to provide a %\index{tactics!using}%[using] clause for the [induction] tactic to specify our alternate principle. *)
1096 1133
1097 induction tr1 using nat_tree_ind'; crush. 1134 induction tr1 using nat_tree_ind'; crush.
1098 1135
1099 (** One subgoal remains: [[ 1136 (** One subgoal remains: [[
1100 n : nat 1137 n : nat
1115 1152
1116 After a few moments of squinting at this goal, it becomes apparent that we need to do a case analysis on the structure of [ls]. The rest is routine. *) 1153 After a few moments of squinting at this goal, it becomes apparent that we need to do a case analysis on the structure of [ls]. The rest is routine. *)
1117 1154
1118 destruct ls; crush. 1155 destruct ls; crush.
1119 1156
1120 (** We can go further in automating the proof by exploiting the hint mechanism. *) 1157 (** We can go further in automating the proof by exploiting the hint mechanism.%\index{Vernacular commands!Hint Extern}% *)
1121 1158
1159 (* begin hide *)
1122 Restart. 1160 Restart.
1161 (* end hide *)
1162 (** %\hspace{-.075in}\coqdockw{%#<tt>#Restart#</tt>#%}%[.] *)
1163
1123 Hint Extern 1 (ntsize (match ?LS with Nil => _ | Cons _ _ => _ end) = _) => 1164 Hint Extern 1 (ntsize (match ?LS with Nil => _ | Cons _ _ => _ end) = _) =>
1124 destruct LS; crush. 1165 destruct LS; crush.
1125 induction tr1 using nat_tree_ind'; crush. 1166 induction tr1 using nat_tree_ind'; crush.
1126 Qed. 1167 Qed.
1127 (* end thide *) 1168 (* end thide *)
1128 1169
1129 (** We will go into great detail on hints in a later chapter, but the only important thing to note here is that we register a pattern that describes a conclusion we expect to encounter during the proof. The pattern may contain unification variables, whose names are prefixed with question marks, and we may refer to those bound variables in a tactic that we ask to have run whenever the pattern matches. 1170 (** We will go into great detail on hints in a later chapter, but the only important thing to note here is that we register a pattern that describes a conclusion we expect to encounter during the proof. The pattern may contain unification variables, whose names are prefixed with question marks, and we may refer to those bound variables in a tactic that we ask to have run whenever the pattern matches.
1130 1171
1131 The advantage of using the hint is not very clear here, because the original proof was so short. However, the hint has fundamentally improved the readability of our proof. Before, the proof referred to the local variable [ls], which has an automatically-generated name. To a human reading the proof script without stepping through it interactively, it was not clear where [ls] came from. The hint explains to the reader the process for choosing which variables to case analyze on, and the hint can continue working even if the rest of the proof structure changes significantly. *) 1172 The advantage of using the hint is not very clear here, because the original proof was so short. However, the hint has fundamentally improved the readability of our proof. Before, the proof referred to the local variable [ls], which has an automatically generated name. To a human reading the proof script without stepping through it interactively, it was not clear where [ls] came from. The hint explains to the reader the process for choosing which variables to case analyze, and the hint can continue working even if the rest of the proof structure changes significantly. *)
1132 1173
1133 1174
1134 (** * Manual Proofs About Constructors *) 1175 (** * Manual Proofs About Constructors *)
1135 1176
1136 (** It can be useful to understand how tactics like [discriminate] and [injection] work, so it is worth stepping through a manual proof of each kind. We will start with a proof fit for [discriminate]. *) 1177 (** It can be useful to understand how tactics like %\index{tactics!discriminate}%[discriminate] and %\index{tactics!injection}%[injection] work, so it is worth stepping through a manual proof of each kind. We will start with a proof fit for [discriminate]. *)
1137 1178
1138 Theorem true_neq_false : true <> false. 1179 Theorem true_neq_false : true <> false.
1139 1180
1140 (* begin thide *) 1181 (* begin thide *)
1141 (** We begin with the tactic [red], which is short for %``%#"#one step of reduction,#"#%''% to unfold the definition of logical negation. *) 1182 (** We begin with the tactic %\index{tactics!red}%[red], which is short for %``%#"#one step of reduction,#"#%''% to unfold the definition of logical negation. *)
1142 1183
1143 red. 1184 red.
1144 (** [[ 1185 (** [[
1145 ============================ 1186 ============================
1146 true = false -> False 1187 true = false -> False
1147 1188
1148 ]] 1189 ]]
1149 1190
1150 The negation is replaced with an implication of falsehood. We use the tactic [intro H] to change the assumption of the implication into a hypothesis named [H]. *) 1191 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]. *)
1151 1192
1152 intro H. 1193 intro H.
1153 (** [[ 1194 (** [[
1154 H : true = false 1195 H : true = false
1155 ============================ 1196 ============================
1157 1198
1158 ]] 1199 ]]
1159 1200
1160 This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *) 1201 This is the point in the proof where we apply some creativity. We define a function whose utility will become clear soon. *)
1161 1202
1162 Definition f (b : bool) := if b then True else False. 1203 Definition toProp (b : bool) := if b then True else False.
1163 1204
1164 (** 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 [f] such that our conclusion of [False] is computationally equivalent to [f false]. Thus, the [change] tactic will let us change the conclusion to [f false]. *) 1205 (** 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}\coqdockw{%#<tt>#change#</tt>#%}% tactic will let us change the conclusion to [toProp false]. The general form %\coqdockw{%#<tt>#change#</tt>#%}% [e] replaces the conclusion with [e], whenever Coq's built-in computation rules suffice to establish the equivalence of [e] with the original conclusion. *)
1165 1206
1166 change (f false). 1207 (* begin hide *)
1208 change (toProp false).
1209 (* end hide *)
1210 (** %\hspace{-.075in}\coqdockw{%#<tt>#change#</tt>#%}% [(][toProp false).] *)
1167 (** [[ 1211 (** [[
1168 H : true = false 1212 H : true = false
1169 ============================ 1213 ============================
1170 f false 1214 toProp false
1171 1215
1172 ]] 1216 ]]
1173 1217
1174 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. *) 1218 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 1219
1176 rewrite <- H. 1220 rewrite <- H.
1177 (** [[ 1221 (** [[
1178 H : true = false 1222 H : true = false
1179 ============================ 1223 ============================
1180 f true 1224 toProp true
1181 1225
1182 ]] 1226 ]]
1183 1227
1184 We are almost done. Just how close we are to done is revealed by computational simplification. *) 1228 We are almost done. Just how close we are to done is revealed by computational simplification. *)
1185 1229
1203 We can perform a similar manual proof of injectivity of the constructor [S]. I leave a walk-through of the details to curious readers who want to run the proof script interactively. *) 1247 We can perform a similar manual proof of injectivity of the constructor [S]. I leave a walk-through of the details to curious readers who want to run the proof script interactively. *)
1204 1248
1205 Theorem S_inj' : forall n m : nat, S n = S m -> n = m. 1249 Theorem S_inj' : forall n m : nat, S n = S m -> n = m.
1206 (* begin thide *) 1250 (* begin thide *)
1207 intros n m H. 1251 intros n m H.
1252 (* begin hide *)
1208 change (pred (S n) = pred (S m)). 1253 change (pred (S n) = pred (S m)).
1254 (* end hide *)
1255 (** %\hspace{-.075in}\coqdockw{%#<tt>#change#</tt>#%}% [(][pred (][S n) = pred (][S m)).] *)
1256
1209 rewrite H. 1257 rewrite H.
1210 reflexivity. 1258 reflexivity.
1211 Qed. 1259 Qed.
1212 (* end thide *) 1260 (* end thide *)
1213 1261
1262 (** The key piece of creativity in this theorem comes in the use of the natural number predecessor function [pred]. Embodied in the implementation of %\coqdockw{%#<tt>#injectivity#</tt>#%}% is a generic recipe for writing such type-specific functions.
1263
1264 The examples in this section illustrate an important aspect of the design philosophy behind Coq. We could certainly design a Gallina replacement that built in rules for constructor discrimination and injectivity, but a simpler alternative is to include a few carefully chosen rules that enable the desired reasoning patterns and many others. A key benefit of this philosophy is that the complexity of proof checking is minimized, which bolsters our confidence that proved theorems are really true. *)
1265
1214 1266
1215 (** * Exercises *) 1267 (** * Exercises *)
1216 1268
1217 (** %\begin{enumerate}%#<ol># 1269 (** %\begin{enumerate}%#<ol>#
1218 1270
1219 %\item%#<li># Define an inductive type [truth] with three constructors, [Yes], [No], and [Maybe]. [Yes] stands for certain truth, [No] for certain falsehood, and [Maybe] for an unknown situation. Define %``%#"#not,#"#%''% %``%#"#and,#"#%''% and %``%#"#or#"#%''% for this replacement boolean algebra. Prove that your implementation of %``%#"#and#"#%''% is commutative and distributes over your implementation of %``%#"#or.#"#%''%#</li># 1271 %\item%#<li># Define an inductive type [truth] with three constructors, [Yes], [No], and [Maybe]. [Yes] stands for certain truth, [No] for certain falsehood, and [Maybe] for an unknown situation. Define %``%#"#not,#"#%''% %``%#"#and,#"#%''% and %``%#"#or#"#%''% for this replacement boolean algebra. Prove that your implementation of %``%#"#and#"#%''% is commutative and distributes over your implementation of %``%#"#or.#"#%''%#</li>#
1220 1272
1221 %\item%#<li># Modify the first example language of Chapter 2 to include variables, where variables are represented with [nat]. Extend the syntax and semantics of expressions to accommodate the change. Your new [expDenote] function should take as a new extra first argument a value of type [var -> nat], where [var] is a synonym for naturals-as-variables, and the function assigns a value to each variable. Define a constant folding function which does a bottom-up pass over an expression, at each stage replacing every binary operation on constants with an equivalent constant. Prove that constant folding preserves the meanings of expressions.#</li># 1273 %\item%#<li># Modify the first example language of Chapter 2 to include variables, where variables are represented with [nat]. Extend the syntax and semantics of expressions to accommodate the change. Your new [expDenote] function should take as a new extra first argument a value of type [var -> nat], where [var] is a synonym for naturals-as-variables, and the function assigns a value to each variable. Define a constant folding function which does a bottom-up pass over an expression, at each stage replacing every binary operation on constants with an equivalent constant. Prove that constant folding preserves the meanings of expressions.#</li>#
1222 1274
1223 %\item%#<li># Reimplement the second example language of Chapter 2 to use mutually-inductive types instead of dependent types. That is, define two separate (non-dependent) inductive types [nat_exp] and [bool_exp] for expressions of the two different types, rather than a single indexed type. To keep things simple, you may consider only the binary operators that take naturals as operands. Add natural number variables to the language, as in the last exercise, and add an %``%#"#if#"#%''% expression form taking as arguments one boolean expression and two natural number expressions. Define semantics and constant-folding functions for this new language. Your constant folding should simplify not just binary operations (returning naturals or booleans) with known arguments, but also %``%#"#if#"#%''% expressions with known values for their test expressions but possibly undetermined %``%#"#then#"#%''% and %``%#"#else#"#%''% cases. Prove that constant-folding a natural number expression preserves its meaning.#</li># 1275 %\item%#<li># Reimplement the second example language of Chapter 2 to use mutually inductive types instead of dependent types. That is, define two separate (non-dependent) inductive types [nat_exp] and [bool_exp] for expressions of the two different types, rather than a single indexed type. To keep things simple, you may consider only the binary operators that take naturals as operands. Add natural number variables to the language, as in the last exercise, and add an %``%#"#if#"#%''% expression form taking as arguments one boolean expression and two natural number expressions. Define semantics and constant-folding functions for this new language. Your constant folding should simplify not just binary operations (returning naturals or booleans) with known arguments, but also %``%#"#if#"#%''% expressions with known values for their test expressions but possibly undetermined %``%#"#then#"#%''% and %``%#"#else#"#%''% cases. Prove that constant-folding a natural number expression preserves its meaning.#</li>#
1224 1276
1225 %\item%#<li># Using a reflexive inductive definition, define a type [nat_tree] of infinitary trees, with natural numbers at their leaves and a countable infinity of new trees branching out of each internal node. Define a function [increment] that increments the number in every leaf of a [nat_tree]. Define a function [leapfrog] over a natural [i] and a tree [nt]. [leapfrog] should recurse into the [i]th child of [nt], the [i+1]st child of that node, the [i+2]nd child of the next node, and so on, until reaching a leaf, in which case [leapfrog] should return the number at that leaf. Prove that the result of any call to [leapfrog] is incremented by one by calling [increment] on the tree.#</li># 1277 %\item%#<li># Using a reflexive inductive definition, define a type [nat_tree] of infinitary trees, with natural numbers at their leaves and a countable infinity of new trees branching out of each internal node. Define a function [increment] that increments the number in every leaf of a [nat_tree]. Define a function [leapfrog] over a natural [i] and a tree [nt]. [leapfrog] should recurse into the [i]th child of [nt], the [i+1]st child of that node, the [i+2]nd child of the next node, and so on, until reaching a leaf, in which case [leapfrog] should return the number at that leaf. Prove that the result of any call to [leapfrog] is incremented by one by calling [increment] on the tree.#</li>#
1226 1278
1227 %\item%#<li># Define a type of trees of trees of trees of (repeat to infinity). That is, define an inductive type [trexp], whose members are either base cases containing natural numbers or binary trees of [trexp]s. Base your definition on a parameterized binary tree type [btree] that you will also define, so that [trexp] is defined as a nested inductive type. Define a function [total] that sums all of the naturals at the leaves of a [trexp]. Define a function [increment] that increments every leaf of a [trexp] by one. Prove that, for all [tr], [total (increment tr) >= total tr]. On the way to finishing this proof, you will probably want to prove a lemma and add it as a hint using the syntax [Hint Resolve name_of_lemma.].#</li># 1279 %\item%#<li># Define a type of trees of trees of trees of (repeat to infinity). That is, define an inductive type [trexp], whose members are either base cases containing natural numbers or binary trees of [trexp]s. Base your definition on a parameterized binary tree type [btree] that you will also define, so that [trexp] is defined as a nested inductive type. Define a function [total] that sums all of the naturals at the leaves of a [trexp]. Define a function [increment] that increments every leaf of a [trexp] by one. Prove that, for all [tr], [total (increment tr) >= total tr]. On the way to finishing this proof, you will probably want to prove a lemma and add it as a hint using the syntax [Hint Resolve name_of_lemma.].#</li>#
1228 1280