**Exercise:** Prove that for any list `xs` and element `x`,
`behead (prepend xs x) ~ xs`, where `prepend` and `behead`
are defined as follows:
```
let prepend xs x =
x::xs
let behead = function
| [] -> []
| _::t -> t
```
*Hint: induction is not needed.*
**Exercise:** Prove that for any list `xs`, `noop xs ~ xs`,
where `noop` is defined as follows:
```
let rec noop = function
| [] -> []
| h::t -> h :: noop t
```
Use the following template for an inductive proof:
```
Theorem: TODO(xs)
Proof: by induction on xs
Case: xs = []
Show: TODO
TODO
Case: xs=h::t
Show: TODO
IH : TODO
TODO
QED
```
* * *
*In the rest of the exercises, continue to use that template for proofs,
and to use structural induction. Make sure for each case to state what you are
trying to show for that case and what the inductive hypotheses are.*
* * *
**Exercise:** Prove that for all `f`, `xs`, and `ys`,
`map f (xs @ ys) = (map f xs) @ (map f ys)`, where
`map` and `(@)` are defined as follows:
```
let rec append l1 l2 =
match l1 with
| [] -> l2
| h::t -> h :: (append t l2)
let (@) = append
let rec map f = function
| [] -> []
| h::t -> (f h) :: map f t
```
**Exercise:** Prove that for all trees `t`, `size (reflect t) ~ size t`,
given the following definitions:
```
type 'a tree = Leaf | Branch of 'a * 'a tree * 'a tree
let rec reflect = function
| Leaf -> Leaf
| Branch(x,l,r) -> Branch(x, reflect r, reflect l)
let rec size = function
| Leaf -> 0
| Branch(x,l,r) -> 1 + size l + size r
```
**Exercise:** Prove that for all functions `f`, `g`, and `h` (of
appropriate types), `(f @@ g) @@ h ~ f @@ (g @@ h)`, where `(@@)`
is defined as follows:
```
let (@@) f g x = f (g x)
```
** *Exercise:** Prove that for all lists `xs`, and for all
lists `ys`, `rev_append xs ys ~ (nrev xs) @ ys`, where `rev_append`
and `nrev` are defined as follows:
```
let rec rev_append l1 l2 =
match l1 with
| [] -> l2
| h :: t -> rev_append t (h :: l2)
let rec nrev = function
| [] -> []
| h::t -> (nrev t) @ [h]
```
*Hint: you will need to use and prove the following lemma.*
```
Lemma: for all lists l1, l2, l3, l1 @ (l2 @ l3) ~ (l1 @ l2) @ l3
```
Next, prove that for all lists `xs`, `rev xs ~ nrev xs`, where
`rev` is defined as follows:
```
let rev xs = rev_append xs []
```
*Hint: state and prove a lemma.*
Note that this definition of `rev` is, in fact, how OCaml's `List.rev` is defined.
You have therefore proved the correctness of a tail-recursive implementation of list
reversal by showing its equivalence to a non-tail-recursive implementation.