Exercise session 1 — Part 2 — Inductive types
- Files:
Module define_nat.Inductive types can be defined using the Inductive keyword
Inductive nat := | O : nat | S : nat -> nat.
EXERCISE
Define addition.
Fixpoint add (n m : nat) {struct n} : nat := match n with | O => m | S n => S (add n m) end.
EXERCISE
Define subtraction on natural numbers, truncating at 0.
In other words, when n < m then sub n m = 0.
Fixpoint sub (n m : nat) : nat := match n, m with | O, _ => O | S n', O => n | S n', S m' => sub n' m' end.
EXERCISE
Prove the following lemma.
You will replace Admitted with Qed once it is done.
What Admitted does should be obvious: it admits a lemma without proof or
with a partial proof, it can be used in subsequent proofs as if it were
proven.
forall n : nat, add n O = nforall n : nat, add n O = nn: natadd n O = nadd O O = On: nat
ih: add n O = nadd (S n) O = S nreflexivity.add O O = On: nat
ih: add n O = nadd (S n) O = S nn: nat
ih: add n O = nS (add n O) = S nreflexivity. Qed.n: nat
ih: add n O = nS n = S n
EXERCISE
forall n m : nat, add n (S m) = S (add n m)forall n m : nat, add n (S m) = S (add n m)n, m: natadd n (S m) = S (add n m)m: natadd O (S m) = S (add O m)n, m: nat
ih: add n (S m) = S (add n m)add (S n) (S m) = S (add (S n) m)reflexivity.m: natadd O (S m) = S (add O m)n, m: nat
ih: add n (S m) = S (add n m)add (S n) (S m) = S (add (S n) m)n, m: nat
ih: add n (S m) = S (add n m)S (add n (S m)) = S (S (add n m))reflexivity. Qed.n, m: nat
ih: add n (S m) = S (add n m)S (S (add n m)) = S (S (add n m))
With the following commands we declare notations for add and sub.
Infix "+" := add. Infix "-" := sub.
EXERCISE
forall n m : nat, n + m - m = nforall n m : nat, n + m - m = nn, m: natn + m - m = nn: natn + O - O = nn, m: nat
ih: n + m - m = nn + S m - S m = nn: natn + O - O = nn: natn - O = nall: reflexivity.O - O = On: natS n - O = S nn, m: nat
ih: n + m - m = nn + S m - S m = nn, m: nat
ih: n + m - m = nS (n + m) - S m = nassumption. Qed.n, m: nat
ih: n + m - m = nn + m - m = n
Note the proof can look nicer if we also prove n - O = n.
forall n : nat, n - O = nforall n : nat, n - O = nn: natn - O = nall: reflexivity. Qed.O - O = On: natS n - O = S nforall n m : nat, n + m - m = nforall n m : nat, n + m - m = nn, m: natn + m - m = nn: natn + O - O = nn, m: nat
ih: n + m - m = nn + S m - S m = nn: natn + O - O = napply sub_O.n: natn - O = nn, m: nat
ih: n + m - m = nn + S m - S m = nn, m: nat
ih: n + m - m = nS (n + m) - S m = nassumption. Qed. End define_nat.n, m: nat
ih: n + m - m = nn + m - m = n
EXERCISE
Define a Boolean predicate deciding equality of natural numbers.
Fixpoint eq_nat (x y : nat) : bool :=
match x, y with
| 0, 0 => true
| 0, S _ => false
| S _, 0 => false
| S x', S y' => eq_nat x' y'
end.EXERCISE
forall n m : nat, eq_nat n m = true <-> n = mforall n m : nat, eq_nat n m = true <-> n = mn, m: nateq_nat n m = true <-> n = mm: nateq_nat 0 m = true <-> 0 = mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) m = true <-> S n = mm: nateq_nat 0 m = true <-> 0 = meq_nat 0 0 = true <-> 0 = 0m: nateq_nat 0 (S m) = true <-> 0 = S meq_nat 0 0 = true <-> 0 = 0true = true <-> 0 = 0all: reflexivity.true = true -> 0 = 00 = 0 -> true = truem: nateq_nat 0 (S m) = true <-> 0 = S mm: natfalse = true <-> 0 = S mall: discriminate.m: natfalse = true -> 0 = S mm: nat0 = S m -> false = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) m = true <-> S n = mn: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) 0 = true <-> S n = 0n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) (S m) = true <-> S n = S mn: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) 0 = true <-> S n = 0n: nat
ih: forall m : nat, eq_nat n m = true <-> n = mfalse = true <-> S n = 0all: discriminate.n: nat
ih: forall m : nat, eq_nat n m = true <-> n = mfalse = true -> S n = 0n: nat
ih: forall m : nat, eq_nat n m = true <-> n = mS n = 0 -> false = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat (S n) (S m) = true <-> S n = S mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat n m = true <-> S n = S mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat n m = true -> S n = S mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = mS n = S m -> eq_nat n m = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = meq_nat n m = true -> S n = S mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = trueS n = S mn, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = truen = massumption.n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = trueeq_nat n m = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = mS n = S m -> eq_nat n m = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S meq_nat n m = truen, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S mn = mreflexivity. Qed.n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S m
H0: n = mm = m
EXERCISE
Definition cur {X Y Z} (f : X * Y -> Z) : X -> Y -> Z :=
fun x y => f (x, y).EXERCISE
Definition car {X Y Z} (f : X -> Y -> Z) : X * Y -> Z :=
fun p =>
match p with
| (x, y) => f x y
end.Note, we can take a shortcut because there is only one constructor so we have a so-called "irrefutable pattern".
Definition car' {X Y Z} (f : X -> Y -> Z) : X * Y -> Z :=
fun '(x,y) => f x y.We could also use fst and snd.
Definition car'' {X Y Z} (f : X -> Y -> Z) : X * Y -> Z :=
fun p => f (fst p) (snd p).EXERCISE
forall (X Y Z : Type) (f : X * Y -> Z) (p : X * Y), car (cur f) p = f pforall (X Y Z : Type) (f : X * Y -> Z) (p : X * Y), car (cur f) p = f pX, Y, Z: Type
f: X * Y -> Z
p: X * Ycar (cur f) p = f preflexivity. Qed.X, Y, Z: Type
f: X * Y -> Z
x: X
y: Ycar (cur f) (x, y) = f (x, y)
EXERCISE
forall (X Y Z : Type) (f : X -> Y -> Z) (x : X) (y : Y), cur (car f) x y = f x yforall (X Y Z : Type) (f : X -> Y -> Z) (x : X) (y : Y), cur (car f) x y = f x y
No intros needed, reflexivity does it for us.
reflexivity. Qed.
EXERCISE
Definition swap {X Y} (p : X * Y) : Y * X :=Irrefutable patterns also work with let.
let '(x, y) := p in
(y, x).EXERCISE
forall (X Y : Type) (p : X * Y), swap (swap p) = pforall (X Y : Type) (p : X * Y), swap (swap p) = pX, Y: Type
p: X * Yswap (swap p) = preflexivity. Qed.X, Y: Type
x: X
y: Yswap (swap (x, y)) = (x, y)
EXERCISE
Prove true <> false without the tactics inversion or discriminate.
Note: a <> b is a notation for a ≠ b, meaning a = b -> False.
true <> falsetrue <> falsee: true = falseFalsee: true = falseif true then False else Trueconstructor. Qed.e: true = falseTrue