CS 334
|
Solution:
fun Curry f s t = f(s,t); fun UnCurry g (s,t) = g s tor equivalently,
fun Curry f = fn s => fn t => f(s,t); fun UnCurry g = fn (s,t) => g s tFor the next part, a proof was required, not an example. Many of you seemed to be willing to believe the following proof that the identity function always returns primes:
OK, here is a real proof that Curry and UnCurry undo each other:
(i) show UnCurry (Curry (f)) (s,t) = f (s,t).
UnCurry (Curry f) (s,t) = (fn (s,t) => (Curry f) s t) (s,t) (by def of UnCurry) = (Curry f) s t = (fn s => fn t => f(s,t)) s t = f (s,t)(ii) show Curry (UnCurry (g)) s t = g s t.
Curry (Uncurry g) s t = (Uncurry g) (s,t) = g s t
a. x and y are considered to have the same type since they are declared together, while z has a different type in the name equivalence, because it is declared with a different descriptive type definition.
b. The best way to fix the code is to give the struct type a name with a typedef and then use the name in all of the declarations. An alternative, not as good, way is to declare them all in the same variable declaration (i.e., erase the second type, and list x,y,z in the first declaration).
a. All of a, b, c, and d are type equivalent under structural equivalence,
b. Only a and b are type equivalent under name equivalence
c. Variables a, b, and c are type equivalent under the actual C rules.
let x = 1 in let g = fn y => succ x in let x = 7 in g 0 end end endShould be 2.
b. What is the correct answer (independent of your interpreter) for the case in which static scoping is desired. 2
c. What is the correct answer for dynamic scoping? 8
datatype value = NUM of int | BOOL of bool | SUCC | PRED | ISZERO | CLOSURE of (string * term * env) | THUNK of term * env | ERROR of string * value withtype env = (string * value) list; (* Note that ERROR terms are used for debugging purposes when an error occurs during expression evaluation. *) fun is_error (ERROR(a,b)) = true | is_error other = false; fun update environ nustr nuval:env = (nustr,nuval)::environ; fun getVal id [] = ERROR (id^"not in environment",NUM 0) | getVal id ((id2,val2)::rest) = if (id = id2) then val2 else getVal id rest; fun newinterp (AST_NUM(n)) (ev:env) = NUM (n) | newinterp (AST_ID(id)) ev = let fun process(THUNK(tm,oldev)) = newinterp tm oldev | process(other) = other in process(getVal id ev) end | newinterp (AST_BOOL(bval)) ev = BOOL(bval) | newinterp (AST_FUN(param,body)) ev = CLOSURE(param,body,ev) | newinterp (AST_SUCC) ev = SUCC | newinterp (AST_PRED) ev = PRED | newinterp (AST_ISZERO) ev = ISZERO | newinterp (AST_ERROR str) ev = ERROR ("In parse", NUM 0) | newinterp (AST_REC(name,body)) ev = let val nuev = update ev name (THUNK(AST_REC(name,body),ev)) in newinterp body nuev end | newinterp (AST_IF(test,yesval,noval)) ev = let val testval = newinterp test ev; fun trueval(BOOL(true)) = true | trueval(x) = false; fun falseval(BOOL(false)) = true | falseval(x) = false; in if trueval(testval) then newinterp yesval ev else if falseval(testval) then newinterp noval ev else ERROR ("if cond not bool",testval) end | newinterp (AST_APP(func,arg)) ev = let val evalfunc = newinterp func ev; val evalarg = newinterp arg ev; fun eval(SUCC,NUM(n)) = NUM(n+1) | eval(PRED,NUM(n)) = if n > 0 then NUM (n-1) else NUM 0 | eval(ISZERO,NUM(n)) = if n = 0 then BOOL(true) else BOOL(false) | eval(CLOSURE(param,body,fev),ERROR (s,v)) = ERROR ((s^" in arg"),v) | eval(CLOSURE(param,body,fev),arg) = let val nuev = update fev param arg in newinterp body nuev end | eval(fst,snd) = ERROR ("no fcn",fst) in eval(evalfunc,evalarg) end;