(* The purpose of the material presented here is to provide first ideas on programming in Coq. Students are expected to carefully read explanations, to run the file, to observe the outputs, and to try to provide answers to exercises. *) (* Reinventing natural numbers *) (* Don't bother on modules for now *) Module Reinvent. Inductive nat : Set := | O : nat | S : nat -> nat. (* A commonly used syntax for Definition pred := fun (n : nat) => match n with etc. *) Definition pred (n : nat) : nat := match n with | O => O | S n' => n' end. (* Let us observe that pred is really fun n : nat => etc. *) Print pred. (* Pattern matching can be done at a deeper level The following could be written Definition minustwo (n : nat) : nat := match n with | O => O | S n' => match n' with | O => O | S n'' => n'' end end. *) Definition minustwo (n : nat) : nat := match n with | O => O | S O => O | S (S n') => n' end. (* Useful constants *) Definition n1 := S O. Definition n2 := S (S O). Definition n3 := S (S (S O)). Definition n4 := S (S (S (S O))). Definition n5 := S n4. Definition n6 := S n5. Definition n9 := S (S (S (S (S (S (S (S (S O)))))))). Definition n10 := S n9. Definition n12 := S (S n10). Eval simpl in (minustwo n4). Check S. Check pred. Check minustwo. (* Next we use an inductive type (bool) defined in the library *) (* It is the same as in lecture02.v *) Print bool. (* Next we use a function (negb) defined in the library *) Compute (negb true). Compute (negb false). Definition oddb (n:nat) : bool := negb (evenb n). (* We check that our definitions return intuitively expected values *) Compute oddb (S O). (* A better way to check this is to state what is the expected value, and then to prove the expected equality *) Example test_oddb1: (oddb (S O)) = true. Proof. reflexivity. Qed. Example test_oddb2: (oddb (S (S (S (S O))))) = false. Proof. reflexivity. Qed. (* Recursive definitions have to be introduced in the following way The syntax is similar to the one above for "pred", with the keyword "Fixpoint" instead of "Definition". *) Fixpoint evenb (n:nat) : bool := match n with | O => true | S p => negb (evenb p) end. (* The typical scheme for programming on natural numbers is Fixpoint some_program (n: nat) : type_of_result := match n with | O => ... | S p => ... (some_program p) ... end. Note that p is structurally smaller than n when n = S p *) (* More functions *) Fixpoint plus (n : nat) (m : nat) : nat := match n with | O => m | S n' => S (plus n' m) end. Fixpoint mult (n m : nat) : nat := match n with | O => O | S n' => plus m (mult n' m) end. (* Another possible definition for even : n' is structurally smaller than n when n = S (S n') *) Fixpoint evenb' (n:nat) : bool := match n with | O => true | S O => false | S (S n') => evenb' n' end. (* You can match two expressions at once. Moreover, note the use of the underscore "_", which stands for a joker. Any pair of values which was not captured by the previous pattern(s) -- here: O, S m' ; S n', O ; or O, O -- is captured there. Writing _ in a pattern is the same as writing some variable that doesn't get used on the right-hand side. The _ avoids the need to make up a bogus name in this case. *) Fixpoint minus (n m:nat) : nat := match n, m with | S n', S m' => minus n' m' | _, _ => n end. Eval compute in (fun n => minus (S n) O). Fixpoint exp (base power : nat) : nat := match power with | O => S O | S p => mult base (exp base p) end. Example test_mult1: (mult n3 n3) = n9. Proof. simpl. reflexivity. Qed. (* Just a trick for allowing as to state exercises *) (* No need to understand it, however here is a very short explanation for curious students: - "fake" provides a value in any Set X. NEVER USE IT IN A REAL DEVELOPMENT - the underscore "_" means "please Coq, guess what should be here from the environment; for instance, if a nat is expected in a given place "fake _" will be understood as "fake nat" - "notation" adds a user-defined syntax to Coq parser. *) Variable fake: forall X: Set, X (* fake value *). Notation admit := (fake _). Fixpoint factorial (n:nat) : nat := (* FILL IN HERE *) admit. Example test_factorial1: (factorial n3) = n6. (* FILL IN HERE *) Admitted. Example test_factorial2: (factorial n5) = (mult n10 n12). (* FILL IN HERE *) Admitted. Notation "x + y" := (plus x y) (at level 50, left associativity) : nat_scope. Notation "x - y" := (minus x y) (at level 50, left associativity) : nat_scope. Notation "x * y" := (mult x y) (at level 40, left associativity) : nat_scope. Check ((O + n1) + n1). (* Test for equality on nat *) Fixpoint beq_nat (n m : nat) : bool := match n with | O => match m with | O => true | S m' => false end | S n' => match m with | O => false | S m' => beq_nat n' m' end end. (* Test for less-or-equal on nat *) Fixpoint ble_nat (n m : nat) : bool := match n with | O => true | S n' => match m with | O => false | S m' => ble_nat n' m' end end. Example test_ble_nat1: (ble_nat n2 n2) = true. Proof. simpl. reflexivity. Qed. Example test_ble_nat2: (ble_nat n2 n4) = true. Proof. simpl. reflexivity. Qed. Example test_ble_nat3: (ble_nat n4 n2) = false. Proof. simpl. reflexivity. Qed. (* Test for less-than on nat *) Definition blt_nat (n m : nat) : bool := (* FILL IN HERE *) admit. Example test_blt_nat1: (blt_nat n2 n2) = false. (* FILL IN HERE *) Admitted. Example test_blt_nat2: (blt_nat n2 n4) = true. (* FILL IN HERE *) Admitted. Example test_blt_nat3: (blt_nat n4 n2) = false. (* FILL IN HERE *) Admitted. (* * Proof by Simplification *) Theorem plus_O_n : forall n:nat, O + n = n. Proof. intros n. reflexivity. Qed. (** Step through this proof in Coq and notice how the goal and context change. *) Theorem plus_1_l : forall n:nat, n1 + n = S n. Proof. intros n. reflexivity. Qed. Theorem mult_0_l : forall n:nat, O * n = O. Proof. intros n. reflexivity. Qed. End Reinvent.