|
CS 334
|
Ex.: If define
- fun updatehd newhd (head::tail) = newhd :: tail;then get sharing:
Safe, because list elt's not updatable!
Ex. Obvious recursive def in ML:
- fun fib 0 : int = 1
| fib 1 = 1
| fib n = fib (n-2) + fib (n-1);
Iterative
solution in Pascal - faster!
Function fastfib (n:integer):integer;
val a,b : integer;
begin
a := 1; b := 1;
while n > 0 do
begin
a := b; b := a + b; n := n-1 (* all done in parallel, else wrong! *)
end;
fib := a
end;
ML equivalent
fun fastfib n = let
fun fibLoop a b 0 = a
| fibLoop a b n : int = fibLoop b (a+b) (n-1)
in
fibLoop 1 1 n
end;
Let's see how you can give a proof of correctness of a functional program:
fun fastfib n : int =
let
fun fibLoop a b 0 = a
| fibLoop a b n : int = fibLoop b (a+b) (n-1)
in
fibLoop 1 1 n
end;
Prove fastfib n = fib n where
fun fib 0 = 1
| fib 1 = 1
| fib n = fib (n-2) + fib (n-1);
Let ai = fib i, for all i.
Therefore a0 = a1 = 1, and ai + ai+1 = ai+2 for all i >= 0, by def of fib.
Theorem: For all i, fibLoop ai ai+1 n = ai+n.
Pf by induction on n:
If n = 0, fibLoop ai ai+1 0 = ai = ai+0 by def.
Suppose true for n - 1:
Then
fibLoop ai ai+1 n = fibLoop ai+1 (ai + ai+1) (n - 1)
= fibLoop ai+1 ai+2 (n - 1)
= ai+1+(n-1) = ai+n.
Now
fastfib n = fibLoop 1 1 n
= fibLoop a0 a1 n
= a0+n
= an
by the Theorem.
Therefore, for all n, fastfib n = fib n.
Similar proofs can be given for other facts, e.g.,
nlength (append l1 l2) = nlength(l1) + nlength(l2)
where
fun nlength [] = 0
| nlength (h::rest) = 1 + nlength rest
and
fun append [] l2 = l2
| append (h::rest) l2 = h :: (append rest l2)