[By Jeff Vaughan] A simple induction proof of the type that might show up on the test: fun pow(int x) = if x=0 then 1 else 2*pow(x-1) show pow is correct. We want to prove that for any positive integer, i, pow(i) = 2^i. We will do this by induction on i, i is an element of Z+0. Base case: pow(0) pow O (fun pow(x) = if x=0 then 1 else 2*pow(x-1)) 0 (if 0=0 then 1 else 2*pow(0-1)) if true then 1 else ... 1 math tells us 2^0 = 1. Therefore the base case is correct. Inductive step: pow(i); i>0 (IH:) Assume that pow(m) = m! for some fixed value value of m (End IH). We will prove that pow(m+1) = m! That is, we will prove {pow(m)=m!} => {pow(m+1)=(m=1)!}. The marked line is the inductive hypothesis. Proof of inductive step: We assumed pow(m) works. Let's try pow(m+1); pow(m+1) (fn x => if x=0 then 1 else 2*pow(m-1) ) (m+1) if m+1 = 0 then 1 else 2*pow(m+1-1) if false then 1 else 2*pow(m+1-1) 2*pow(m+1-1) 2*pow(m) 2*2^m by the IH 2^(m+1) by math so for the inductive case we've shown pow(m)=2^m => pow(m+1)=2^(m+1). With the base case, this proves that for all x element of Z+0, pow x = 2^x. QED. Note: This deviates very slightly from what the lecture. In lecture the students learned to unroll the function (in this case pow) at the same time as substitution arguments for the formal parameters. I delay the unrolling until the evalulation of pow. This gives us a more consistant way to handle named function calls which are recursive. 2. Functors Functors allow us to parameterize a structure. You can think of a functor as a function which takes and returns sturctures instead of normal values. You can't do anything with functor directly. Instead, you must pass it a structure and use the structure it returns. On reason to use functors is to provide a common interface for several implementations of data structure or a module. In the problem set the interpreter is a functor which can take different envirnoments. This useful because it may not be obvious what techniques will have the best proformance in real life. There's a good example of a funcorized binary search tree at: http://www.cs.cornell.edu/courses/cs312/2002sp/lectures/rec10.asp Several key points: * ORD_SET is a signature declared in the basis library. Students should be familiar with it. * Although we could not use a functor and just pass a compare function separately to every call of, for example, add, this is a bad idea. In particular, if we passed two compare different functions on subsequent adds, the tree could become broken. Alternatively imagine doing a lookup with a different comparison than what was used to insert. * Functors don't solve all the above problems. For example, you could have a "broken" comparison function that says a