CS312 Lecture 12: Prelim #1 Review

Overview

Administrivia: PS#3 due in about 36 hours. PS#4 won't be out until after the prelim (studying for the prelim is a better use of your time...)

General Information about the prelim

Notes on induction and the substitution model

Induction example

Write a recursive function that takes an 'a list and returns a copy of it. Prove that your function is correct, using induction and the substitution model. You may assume that the list primitives null,hd,tl,:: operate correctly.

fun copy(l:'a list):'a list =
     if null(l) then l else hd(l)::copy(tl(l))

Correctness proof:

  1. Precise statement of P[n]: copy(lst) = lst, where lst is a list of length n.
  2. Induction on n in W (whole numbers)
  3. We need to show P[0]. See below.
  4. We need to show that for all m, P[m]=>P[m+1]. See below.
Base case: lst has length 0.
eval(let fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l)) in fact(1st) end)

Þ

  eval((fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l))) (1st))

Þ

  eval(if null?(lst) then lst
    else ((fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l)))(lst))

Þ  [because length of lst = 0]

  lst 
Induction case: lst has length m+1, copy works on lists of length m.
eval(let fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l)) in fact(1st) end)

Þ

  eval((fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l))) (1st))

Þ

  eval(if null?(lst) then lst
    else ((fun copy(l) = if null?(l) then l else hd(l)::copy(tl(l)))(lst))

Þ  [because length of lst = m+1 which is >0]

eval(hd(lst)::copy(tl(lst)))

Þ  [by IH, since tl(lst) has length m+1-1= m]

eval(hd(lst)::tl(lst))

Þ  [by the semantics of the list primitives]

lst

Some old prelim questions and answers

Evaluate each of the following ML expressions and say what value (if any) is produced by the code. You need not justify each and every step of the evaluation, but if you get the wrong answer, then we are likely to give partial credit if we can follow your reasoning using the Substitution Model.

a.  let val (x,y) = (2+4, 8-1) in y*x end
 
Answer:  42

b.  (((fn x => (fn y => y*x)) (2*3)) (5+2))
 
Answer:  42
 
c.  let val f = (fn x => (fn y => (fn z => x*z+y)))
        val g = f(2)
    in
        (g(3))(5)
    end
 
Answer:  13
 
e.  let val f = 
        let val x = (fn x => (fn y => x))
            val y = (fn x => (fn y => (fn z => ((x z) (y z)))))
        in
            (y x) x
        end
    in
       f
    end
 
Answer:  fn z => (((fn x => (fn y => x)) z) ((fn x => (fn y => x)) z)))
 
f.  let fun f (g: 'a -> 'b -> 'b) (x: 'b) (y: 'a list): 'b = 
               case y of
                 nil => x
               | h::t => f g (g h x) t
        val r = f (fn x => (fn y => (x+1)::y)) nil
    in
       r (1::2::3::nil)
    end
 
Answer:  4::3::2::nil = [4,3,2]
 
g.  let fun f(x:int):int = 
        let fun g(y:int):int = if (y > 0) then f(y-1) else y
        in
            g(x+1)
        end
    in
       f(~1)
    end
 
Answer:  0

Recall the definition of foldl:

   fun foldl (f: ('a*'b) -> 'b) (base:'b) (x:'a list):'b = 
       case x of
         nil => base
       | hd::tl => foldl f (f (hd,base)) tl
For each of the following tasks, show how foldl can be used to do that task in one line of code.
a.  Sum the elements of a list of integers x.

Sample Answer:  foldl (op +) 0 x

b.  Count the number of elements in a list x.

Sample Answer:  foldl (fn (_,i) => i+1) 0 x

c.  Filter out all of the numbers less than zero in a list of integers x.

Sample Answer:
   foldl (fn (i,xs) => if i < 0 then xs else i::xs) [] x

Complete each of the following let-expressions by replacing "???" with a value that causes the whole thing to evaluate to the integer 42. Again, you can simply write down an answer, but to receive partial credit for the wrong answer, you should justify your choice using the Substitution Model.

a.  let fun zardoz(x: int list):int =
            case x of
              nil => 0
            | x::nil => 41
            | x::y::nil => x
            | _ => 3
    in
       zardoz(???)
    end
 
Sample Answer:  42::1::nil = [42,1]  (any value other than 1 will work too)
 
b.  let fun zardoz(x: int list, y: int list, z:int list):int =
            case (x, y, z) of
              (x1::nil, _, c) => 0
            | (a, 3::b::c, d) => 1
            | (nil, nil, nil) => 2
            | (a, b, 2::d::e) => 3
            | (a::_, b::_, _) => a+b
            | _ => 43
    in
       zardoz(???)
    end
 
Sample Answer:  (42::1::nil, 0::nil, nil)
 
c.  type t = {foo:(int*real), bar:(real*int)}
    
    let fun zardoz(x:t) = 
            let val p = #bar x
                val q = #foo x
            in
               (#2 p) - (#1 q)
            end
    in
       zardoz(???)
    end
 
Sample Answer:  {foo=(0,3.14), bar=(2.17,42)}
 
d.  let val x = (2,5)
        val y = (3,7)
        val f = (fn (x:int*int,y:int*int) => (#1 x,(#2 x)*(#2 y)))
        val g = (fn (x:int,y:int) => (y,x))
        val h = (fn (x:int,y:int) => x)
        fun zardoz(f:int*int->int*int, g:(int*int)*(int*int)->int*int):int =
            h(f(g(g(f(x),f(y)),y)))
    in
       zardoz(???)
    end
 
Sample Answer:  zardoz(g, f) - hint, look at the type of zardoz

CS312  © 2002 Cornell University Computer Science