Exercise session 1 — Part 2 — Inductive types

Authors:

Yannick Forster

Théo Winterhalter

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

forall n : nat, add n O = n
n: nat

add n O = n

add O O = O
n: nat
ih: add n O = n
add (S n) O = S n

add O O = O
reflexivity.
n: nat
ih: add n O = n

add (S n) O = S n
n: nat
ih: add n O = n

S (add n O) = S n
n: nat
ih: add n O = n

S n = S n
reflexivity. Qed.

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: nat

add n (S m) = S (add n m)
m: nat

add 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)
m: nat

add O (S m) = S (add O m)
reflexivity.
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))
n, m: nat
ih: add n (S m) = S (add n m)

S (S (add n m)) = S (S (add n m))
reflexivity. Qed.

With the following commands we declare notations for add and sub.

  Infix "+" := add.
  Infix "-" := sub.

EXERCISE

  

forall n m : nat, n + m - m = n

forall n m : nat, n + m - m = n
n, m: nat

n + m - m = n
n: nat

n + O - O = n
n, m: nat
ih: n + m - m = n
n + S m - S m = n
n: nat

n + O - O = n
n: nat

n - O = n

O - O = O
n: nat
S n - O = S n
all: reflexivity.
n, m: nat
ih: n + m - m = n

n + S m - S m = n
n, m: nat
ih: n + m - m = n

S (n + m) - S m = n
n, m: nat
ih: n + m - m = n

n + m - m = n
assumption. Qed.

Note the proof can look nicer if we also prove n - O = n.

  

forall n : nat, n - O = n

forall n : nat, n - O = n
n: nat

n - O = n

O - O = O
n: nat
S n - O = S n
all: reflexivity. Qed.

forall n m : nat, n + m - m = n

forall n m : nat, n + m - m = n
n, m: nat

n + m - m = n
n: nat

n + O - O = n
n, m: nat
ih: n + m - m = n
n + S m - S m = n
n: nat

n + O - O = n
n: nat

n - O = n
apply sub_O.
n, m: nat
ih: n + m - m = n

n + S m - S m = n
n, m: nat
ih: n + m - m = n

S (n + m) - S m = n
n, m: nat
ih: n + m - m = n

n + m - m = n
assumption. Qed. End define_nat.

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

forall n m : nat, eq_nat n m = true <-> n = m
n, m: nat

eq_nat n m = true <-> n = m
m: nat

eq_nat 0 m = true <-> 0 = m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
eq_nat (S n) m = true <-> S n = m
m: nat

eq_nat 0 m = true <-> 0 = m

eq_nat 0 0 = true <-> 0 = 0
m: nat
eq_nat 0 (S m) = true <-> 0 = S m

eq_nat 0 0 = true <-> 0 = 0

true = true <-> 0 = 0

true = true -> 0 = 0

0 = 0 -> true = true
all: reflexivity.
m: nat

eq_nat 0 (S m) = true <-> 0 = S m
m: nat

false = true <-> 0 = S m
m: nat

false = true -> 0 = S m
m: nat
0 = S m -> false = true
all: discriminate.
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat (S n) m = true <-> S n = m
n: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat (S n) 0 = true <-> S n = 0
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
eq_nat (S n) (S m) = true <-> S n = S m
n: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat (S n) 0 = true <-> S n = 0
n: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

false = true <-> S n = 0
n: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

false = true -> S n = 0
n: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
S n = 0 -> false = true
all: discriminate.
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat (S n) (S m) = true <-> S n = S m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat n m = true <-> S n = S m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat n m = true -> S n = S m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
S n = S m -> eq_nat n m = true
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

eq_nat n m = true -> S n = S m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = true

S n = S m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = true

n = m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: eq_nat n m = true

eq_nat n m = true
assumption.
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m

S n = S m -> eq_nat n m = true
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S m

eq_nat n m = true
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S m

n = m
n, m: nat
ih: forall m : nat, eq_nat n m = true <-> n = m
h: S n = S m
H0: n = m

m = m
reflexivity. Qed.

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 p

forall (X Y Z : Type) (f : X * Y -> Z) (p : X * Y), car (cur f) p = f p
X, Y, Z: Type
f: X * Y -> Z
p: X * Y

car (cur f) p = f p
X, Y, Z: Type
f: X * Y -> Z
x: X
y: Y

car (cur f) (x, y) = f (x, y)
reflexivity. Qed.

EXERCISE


forall (X Y Z : Type) (f : X -> Y -> Z) (x : X) (y : Y), cur (car f) x y = f x y

forall (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) = p

forall (X Y : Type) (p : X * Y), swap (swap p) = p
X, Y: Type
p: X * Y

swap (swap p) = p
X, Y: Type
x: X
y: Y

swap (swap (x, y)) = (x, y)
reflexivity. Qed.

EXERCISE

Prove true <> false without the tactics inversion or discriminate.

Note: a <> b is a notation for a ≠ b, meaning a = b -> False.


true <> false

true <> false
e: true = false

False
e: true = false

if true then False else True
e: true = false

True
constructor. Qed.