| 
CS 334
 | 
Solution:
fun Curry f s t = f(s,t);
       
fun UnCurry g (s,t) = g s t
    
or equivalently,
        fun Curry f = fn s => fn t => f(s,t);
        fun UnCurry g = fn (s,t) => g s t
For 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 end
 Should 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;