Exercise session 2 — Part 1
🏠 Go back to the course homepage.
Inductive types can be defined using the Inductive keyword
EXERCISE
Define addition.
EXERCISE
Define subtraction on natural numbers, truncating at 0. In other words, when n < m then sub n m = 0.
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.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.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.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.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.n, m: nat
ih: n + m - m = nn + m - m = n
EXERCISE
Define a Boolean predicate deciding equality of natural numbers.
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.n, m: nat
ih:= forall m: nat, eq_nat n m = true <-> n = m
h: S n = S m
H0: n = mm = m
EXERCISE
EXERCISE
Note, we can take a shortcut because there is only one constructor so we have a so-called "irrefutable pattern".
We could also use fst and snd.
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.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.
EXERCISE
Definition swap {X Y} (p : X * Y) : Y * X :=
Irrefutable patterns also work with let.
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.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.e: true = falseTrueFrom Stdlib Require Import List. Import ListNotations.
EXERCISE
Prove the following. You will need lemmas, prove them yourself by induction and do not use lemmas from the standard library.
forall (A : Type) (l : list A), l ++ [] = lforall (A : Type) (l : list A), l ++ [] = lA: Type
l: list Al ++ [] = lA: Type[] ++ [] = []A: Type
a: A
l: list A
ih: l ++ [] = l(a :: l) ++ [] = a :: lreflexivity.A: Type[] ++ [] = []A: Type
a: A
l: list A
ih: l ++ [] = l(a :: l) ++ [] = a :: lA: Type
a: A
l: list A
ih: l ++ [] = la :: l ++ [] = a :: lreflexivity.A: Type
a: A
l: list A
ih: l ++ [] = la :: l = a :: lforall (A : Type) (u v w : list A), (u ++ v) ++ w = u ++ v ++ wforall (A : Type) (u v w : list A), (u ++ v) ++ w = u ++ v ++ wA: Type
u, v, w: list A(u ++ v) ++ w = u ++ v ++ wA: Type
v, w: list A([] ++ v) ++ w = [] ++ v ++ wA: Type
a: A
u, v, w: list A
ih: (u ++ v) ++ w = u ++ v ++ w((a :: u) ++ v) ++ w = (a :: u) ++ v ++ wreflexivity.A: Type
v, w: list A([] ++ v) ++ w = [] ++ v ++ wA: Type
a: A
u, v, w: list A
ih: (u ++ v) ++ w = u ++ v ++ w((a :: u) ++ v) ++ w = (a :: u) ++ v ++ wA: Type
a: A
u, v, w: list A
ih: (u ++ v) ++ w = u ++ v ++ wa :: (u ++ v) ++ w = a :: u ++ v ++ wreflexivity.A: Type
a: A
u, v, w: list A
ih: (u ++ v) ++ w = u ++ v ++ wa :: u ++ v ++ w = a :: u ++ v ++ wforall (A : Type) (l1 l2 : list A), rev (l1 ++ l2) = rev l2 ++ rev l1forall (A : Type) (l1 l2 : list A), rev (l1 ++ l2) = rev l2 ++ rev l1A: Type
l1, l2: list Arev (l1 ++ l2) = rev l2 ++ rev l1A: Type
l2: list Arev ([] ++ l2) = rev l2 ++ rev []A: Type
a: A
l1, l2: list A
ih: rev (l1 ++ l2) = rev l2 ++ rev l1rev ((a :: l1) ++ l2) = rev l2 ++ rev (a :: l1)A: Type
l2: list Arev ([] ++ l2) = rev l2 ++ rev []A: Type
l2: list Arev l2 = rev l2 ++ []reflexivity.A: Type
l2: list Arev l2 = rev l2A: Type
a: A
l1, l2: list A
ih: rev (l1 ++ l2) = rev l2 ++ rev l1rev ((a :: l1) ++ l2) = rev l2 ++ rev (a :: l1)A: Type
a: A
l1, l2: list A
ih: rev (l1 ++ l2) = rev l2 ++ rev l1rev (l1 ++ l2) ++ [a] = rev l2 ++ rev l1 ++ [a]A: Type
a: A
l1, l2: list A
ih: rev (l1 ++ l2) = rev l2 ++ rev l1(rev l2 ++ rev l1) ++ [a] = rev l2 ++ rev l1 ++ [a]reflexivity.A: Type
a: A
l1, l2: list A
ih: rev (l1 ++ l2) = rev l2 ++ rev l1rev l2 ++ rev l1 ++ [a] = rev l2 ++ rev l1 ++ [a]
EXERCISE
X: Type
l: list Xrev (rev l) = lX: Type
l: list Xrev (rev l) = lX: Typerev (rev []) = []X: Type
x: X
l: list X
ih: rev (rev l) = lrev (rev (x :: l)) = x :: lreflexivity.X: Typerev (rev []) = []X: Type
x: X
l: list X
ih: rev (rev l) = lrev (rev (x :: l)) = x :: lX: Type
x: X
l: list X
ih: rev (rev l) = lrev (rev l ++ [x]) = x :: lX: Type
x: X
l: list X
ih: rev (rev l) = lrev [x] ++ rev (rev l) = x :: lX: Type
x: X
l: list X
ih: rev (rev l) = lrev [x] ++ l = x :: lreflexivity.X: Type
x: X
l: list X
ih: rev (rev l) = lx :: l = x :: l
EXERCISE
forall (A : Type) (l : list A), fast_rev l [] = rev lforall (A : Type) (l : list A), fast_rev l [] = rev lA: Type
l: list Afast_rev l [] = rev lA: Type
l: list Aforall acc : list A, fast_rev l acc = rev l ++ accA: Type
l: list A
h:= forall acc: list A, fast_rev l acc = rev l ++ accfast_rev l [] = rev lA: Type
l: list Aforall acc : list A, fast_rev l acc = rev l ++ accA: Typeforall acc : list A, fast_rev [] acc = rev [] ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ accforall acc : list A, fast_rev (a :: l) acc = rev (a :: l) ++ accA: Typeforall acc : list A, fast_rev [] acc = rev [] ++ accA: Type
acc: list Afast_rev [] acc = rev [] ++ accreflexivity.A: Type
acc: list Aacc = accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ accforall acc : list A, fast_rev (a :: l) acc = rev (a :: l) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Afast_rev (a :: l) acc = rev (a :: l) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Afast_rev l (a :: acc) = (rev l ++ [a]) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = (rev l ++ [a]) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = rev l ++ [a] ++ accreflexivity.A: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = rev l ++ a :: accA: Type
l: list A
h:= forall acc: list A, fast_rev l acc = rev l ++ accfast_rev l [] = rev lA: Type
l: list A
h: fast_rev l [] = rev l ++ []fast_rev l [] = rev lassumption.A: Type
l: list A
h: fast_rev l [] = rev lfast_rev l [] = rev l
Note we could have done it without the assert using generalize.
forall (A : Type) (l : list A), fast_rev l [] = rev lforall (A : Type) (l : list A), fast_rev l [] = rev lA: Type
l: list Afast_rev l [] = rev lA: Type
l: list Afast_rev l [] = rev l ++ []A: Type
l: list Aforall acc : list A, fast_rev l acc = rev l ++ accA: Typeforall acc : list A, fast_rev [] acc = rev [] ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ accforall acc : list A, fast_rev (a :: l) acc = rev (a :: l) ++ accA: Typeforall acc : list A, fast_rev [] acc = rev [] ++ accA: Type
acc: list Afast_rev [] acc = rev [] ++ accreflexivity.A: Type
acc: list Aacc = accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ accforall acc : list A, fast_rev (a :: l) acc = rev (a :: l) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Afast_rev (a :: l) acc = rev (a :: l) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Afast_rev l (a :: acc) = (rev l ++ [a]) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = (rev l ++ [a]) ++ accA: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = rev l ++ [a] ++ accreflexivity.A: Type
a: A
l: list A
ih:= forall acc: list A, fast_rev l acc = rev l ++ acc
acc: list Arev l ++ a :: acc = rev l ++ a :: acc