# Code specifications

To avoid doubt about “properties of lists” we can state properties using only code:

``````let rec append l1 l2 = match l1 with
| [] -> l2
| h::t -> h::(append t l2)

let rec sum = function [] -> 0
| h::t -> h + (sum t)``````

Claim:`ℓ₁ : int list`:

`ℓ₂ : int list`,

`sum (append ℓ₁ ℓ₂) ≡ (sum ℓ₁) + (sum ℓ₂)`

Base Case: `ℓ₁ = []`.

Inductive Case: Need to show that:

``````sum (append ℓ₁ ℓ₂) ≡ (sum ℓ₁) + (sum ℓ₂) ⇒
sum (append (x::ℓ₁) ℓ₂) ≡ (sum (x::ℓ₁)) + (sum ℓ₂)``````

# Lemma Example

``````let rev lst =
let rec tail_rev lst acc = match lst with
| [] -> acc
| h::t -> tail_rev t (h::acc)
in tail_rev lst []``````

To prove that ∀ `ℓ : 'a list`, `rev ℓ ≡ reverse ℓ`, we’ll first prove:

Lemma.

∀`ℓ₁,ℓ₂ : 'a list`, `(tail_rev ℓ₁ ℓ₂) ≡ (reverse ℓ₁) @ ℓ₂`

Base Case: `ℓ₁ = []`.

Inductive Case: Need to show

``````tail_rev ℓ₁ ℓ₂ ≡ (reverse ℓ₁) @ ℓ₂ ⇒
tail_rev (x::ℓ₁) ℓ₂ ≡ (reverse (x::ℓ₁)) @ ℓ₂``````

Informally we are proving that `P(ℓ)` is invariant over recursive calls.

Can’t you prove any (even false) thing(s) this way?

Consider “broken” versions of `append`, `tail_rev`:

``````let rec badpend l1 l2 = match l1 with
| [] -> l2
| h::t -> badpend l1 l2``````

(IH only tells about `(badpend t l2)`)

``````let rec fail_rev l1 acc = match l1 with
| [] -> []
| h::t -> fail_rev t (h::acc)``````

(Base case is wrong…)

## Generalized Induction

For any inductive type of the form:

``````type t = C₀ of b (* b is some other type not referring to t *)
| C₁ of b₁*t``````

The principle of induction for type `t` is:
For all `x : t`, `P(x)` if:

• `v : b`, `P(C₀ v)`, and
• `x : t, v : b₁`, `P(x) ⇒ P(C₁(v,x))`

Examples:

• `nat`: ∀ `n : nat`, `P(n)` if `P(Zero)` and `∀ m`, `P(m) ⇒ P(Succ m)`
• `'a list`: ∀ `ℓ : 'a list`, `P(ℓ)` if
`P([])` and `∀ x : 'a`, `∀ ℓ : 'a list`, `P(ℓ) ⇒ P(x::ℓ)`

More Generalized Induction…

``type bitlist = C0 | C1 | L0 of bitlist | L1 of bitlist``

Principle of structural induction for `bitlist`:

`ℓ : bitlist`, `P(ℓ)` if:

• `P(C0)`, and
• `P(C1)`, and
• ∀ ℓ, `P(ℓ) ⇒ P(L0 ℓ)`, and
• ∀ ℓ, `P(ℓ) ⇒ P(L1 ℓ)`

Notice: Here we have two base cases, and two step cases.

``````let rec bitlen blst = match blst with
| C0 | C1 -> 1
| L0 b | L1 b -> 1 + (bitlen b)

let rec bitweight blst = match blst with
| C0 -> 0
| C1 -> 1
| L0 b -> bitweight b
| L1 b -> 1 + (bitweight b)``````

Prove:`bl : bitlist`, `bitweight bl <= bitlen bl`

Prove:`bl : bitlist`, `bitweight bl <= bitlen bl`

Base Cases:

`bitweight C0 <= bitlen C0`

`bitweight C1 <= bitlen C1`

Inductive Cases: Need to show

``````bitweight ℓ <= bitlen ℓ ⇒
bitweight (L0 ℓ) <= bitlen (L0 ℓ)``````

and

``````bitweight ℓ <= bitlen ℓ ⇒
bitweight (L1 ℓ) <= bitlen (L1 ℓ)``````

# `cs2041.org`

// reveal.js plugins