module Num = mixin body type term = Const of int | Add of term * term type value = Num of int type env let rec eval tm (e:env) = match tm with | Const i -> Num i | Add (t1, t2) -> begin match eval t1, eval t2 with | Num i, Num j -> Num (i + j) | _ -> failwith "Num.eval: type mismatch" end | tm -> inner tm e end (* Num *) module Func = mixin let bind (x, v, e) = fun y -> if x=y then v else e y body type term = Var of string | Abs of string * term | App of term * term type value = Clos of term * env and env = string -> value let eval tm (e:env) = match tm with | Var x -> e x | Abs _ as f -> Clos (f, e) | App (rator, rand) e -> begin match eval rator e with | Clos (Abs (x, b), e') -> eval b (bind (x, eval rand e, e')) | _ -> failwith "Func.eval: type mismatch" end | _ -> inner tm e end (* Func *)