(* HW1: Supporting code *) type var = string type exp = Abs of var * exp | App of exp * exp | Var of var (* is_free v e returns true iff v is free in e *) let rec is_free (v:var) (e:exp) : bool = match e with Abs(w,e') -> (v <> w) && (is_free v e') | App(a,b) -> (is_free v a) || (is_free v b) | Var w -> (v=w) (* rename v returns v where n is a fresh integer *) let rename : string -> string = let c = ref 0 in function v -> let s = v ^ string_of_int (!c) in incr c; s (* subst e v e' returns a copy of expression e' with all free occurrences of v replaced by e *) let rec subst (e:exp) (v:var) (e':exp) : exp = match e' with Var w -> if w=v then e else e' | App(a,b) -> App(subst e v a, subst e v b) | Abs(w,b) -> if w=v then e' else if is_free v b && is_free w e then let z = rename w in Abs(z, subst e v (subst (Var z) w b)) else Abs(w, subst e v b) (* reduce e returns a version of e with all outermost redexes reduced; this may of course create new redexes. *) let rec reduce (e:exp) : exp = match e with App(Abs(v,a),b) -> subst b v a | Abs(v,e) -> Abs(v, reduce e) | App(a,b) -> App(reduce a, reduce b) | Var _ -> e (* show e prints an abbreviated concrete syntax representation of e to stdout *) let show (e:exp) : unit = let rec print_exp e = match e with Abs _ -> (print_string "("; print_abs e; print_string ")" ) | App _ -> (print_string "("; print_app e; print_string ")") | Var s -> print_string s and print_abs e = match e with Abs(v,e) -> (print_string "\\"; print_string v; print_string "."; print_abs e) | _ -> print_app e and print_app e = match e with App(a,b) -> (print_app a; print_string " "; print_exp b) | _ -> print_exp e in print_exp e; print_newline() (* Some lambda terms describing Church numerals and operators on them. *) let zero = Abs("f",Abs("x",Var "x")) let one = Abs("f",Abs("x",App(Var "f",Var "x"))) let three = Abs("f",Abs("x",App(Var "f",App(Var "f",App(Var "f",Var "x"))))) let add = Abs("n",Abs("m",Abs("f",Abs("x",App(App(Var "n",Var "f"), App(App(Var "m",Var "f"),Var "x")))))) let succ = App(add,one) let d = Abs("x",App(Var "x",Var "x")) let dd = App(d,d)