type var = string type value = int datatype exp = Val of value | Var of var | Plus of exp * exp | Times of exp * exp | Let of exp * var * exp fun subst (v, x, Val w) = Val w | subst (v, x, Var y) = if x = y then Val v else Var y | subst (v, x, Plus (e1, e2)) = Plus (subst (v, x, e1), subst (v, x, e2)) | subst (v, x, Times (e1, e2)) = Times (subst (v, x, e1), subst (v, x, e2)) | subst (v, x, Let (e1, y, e2)) = Let (subst (v, x, e1), y, if x = y then e2 else subst (v, x, e2)) fun binop (f, c, Val x, Val y) = SOME (Val (f (x, y))) | binop (f, c, e1 as Val _, e2) = (case onestep e2 of NONE => NONE | SOME e2' => SOME (c (e1, e2'))) | binop (f, c, e1, e2) = (case onestep e1 of NONE => NONE | SOME e1' => SOME (c (e1', e2))) and onestep (Plus (e1, e2)) = binop (op +, Plus, e1, e2) | onestep (Times (e1, e2)) = binop (op *, Times, e1, e2) | onestep (Let (Val v, x, e2)) = SOME (subst (v, x, e2)) | onestep (Let (e1, x, e2)) = (case onestep e1 of NONE => NONE | SOME e1' => SOME (Let (e1', x, e2))) | onestep _ = NONE fun multistep e = case onestep e of NONE => e | SOME e' => multistep e'