We
should make a few points about proofs/formal reasoning in the context of
fun O2 x y z = x (y z)
Most
important point:
fun O2 x y z = x (y z)
is
a shorthand for
val O2 = fn x => (fn y => (fn z
=> z(y z)))
It
is much easier to reason about O2 by converting it to this form.
For
question 2: O2 O2 O2 = O2 o O2
(fn
x => (O2 o O2) x) equals (fn x = > O2 (O2 (x) ))
but
O2
o O2 is not equal to O2 O2
Because
O2 O2 equals fn x => O2 O2 x equals fn x => (O2 O2) x
And
O2 o O2 equals fn x => O2(O2 x)
But
fn x => (O2 O2) x does not equal fn x => O2(O2(x))
You can see this by reasoning about the types. The RHS expression will compile if O2: int->int, but the LHS will not. I use the word equals to mean that two functions, when applied to any argument, yield the same result. Some students answered part one by explaining O2 in terms of itself. This is not helpful, and students lost credit for it. The concise answer is O2 is a curried composition function.
In
part 2 students needed to be formal.
RSM reduces to: eval, apply, eval, apply, eval, apply, eval, apply,
eval, apply....
Example:
(fn x=> (fn y => x x y)) (let foo = fn x => x in foo end) 3
Left
associativity lets us this the same as
((fn x=> (fn y => x x y)) (let foo = fn x => x in foo end)) 3
evaluating
the left expression does nothing.
Evaluating the let expression
gives
((fn x=> (fn y => x x y)) (fn x => x)) 3
Apply (fn x=> (fn y => x x y)) to
(fn x => x) by
substituting
[fn x =>x /x] in (fn x=> (fn y => x x y) *one notation*
(fn y => (fn x => x) (fn x =>
x) y) 3
Eval
the left expression... already a value
Eval
the right expression ... 3 ->3
Apply
(fn y => (fn x => x) (fn x => x) y) 3 by
Substituting: (fn y => (fn x => x) (fn x => x) y)
[3/y] *another notation*
(fn x => x) (fn x => x) 3
Eval
left expression ... (fn x => x) already a value
Eval
right expression ... (fn x => x) already a value
Apply
(fn x => x) (fn x => x) by
Substituting
(fn x => x)[(fn x => x)/x]
(fn x => x) 3
Eval
left expression ... (fn x => x) already a value
Eval
left expression ... 3 already a value
Apply
(fn x => x) (fn x => x) by
Subsituting
(fn x => x)[3/x]
3
Eval
3
Answer
is 3
Important note: functions are applied to their arguments f(x) means f applied to x. Some students wrote x applied to f, which is very wrong.
Here
is another way of reasoning about problem 2 b:
Let f, g, x, y be the four
arguments required for expression O2 O2 O2. We need to prove that for all
choices of f, g, x, y of the appropriate types we have the following equality:
(O2
o O2) f g x y = (O2 O2 O2) f g x y
We will rewrite each expression using the definition of the function
composition operator o and O2. At each step we will use (sometimes redundant)
parentheses to show the arguments that apply to each function.
(O2
o O2) f g x y
=
(O2 (O2 f)) g x y [definition of
operator o]
=
O2 (O2 f) g x y [*]
=
(O2 f) (g x) y [definition of O2]
=
O2 f (g x) y
=
f((g x) y) [definition of O2]
=
f(g x y)
(O2
O2 O2) f g x y
=
(O2 O2 O2 f) g x y
=
O2 (O2 f) g x y [**]
=
f(g x y)
The expression [**] is identical to [*], and it shows the
equivalence of O2 O2 O2 and O2 o O2. Following exactly the same steps in the
derivation as above we reach the same final result, which also explains what
the function does.
Problem
3:
For
induction just run over the 4 steps:
There
are four parts two and induction proof:
1.
State what you want to prove
2. State what you will do induction on
(often one or "math
words," like
"positive
integers," is appropriate)
3. Prove the base case (e.g. P[0])
4. Prove the inductive case. (e.g. P[m] => P[m+1])
4 1/2. State the induction hypothesis
4 3/4. Clearly label where you use the induction hypothesis
4 7/8. State your conclusion
Key
things to look for:
-
Did you prove correctness for the entire domain of the function?
Eg. Base case is 0 or 1?
-
Did you label your IH when you state it initially and when you
use it?
This is not strictly necessary, but is essential if you
want to see any partial credit.