(* Reducers (interpreters) for lambda-calculus. *) open Utils open Parser exception OutOfVariablesError let possible_variables = List.map (fun x -> char_to_string (char_of_int x)) ((range 97 123) @ (range 65 91)) let fresh_var used_vars : string = if StringSet.is_empty (StringSet.diff (string_set_from_list(possible_variables)) used_vars) then raise (OutOfVariablesError) else StringSet.choose (StringSet.diff (string_set_from_list(possible_variables)) used_vars) let rec fv = fun t -> match t with | Variable(x) -> let set = StringSet.empty in StringSet.add x set in set | Abstraction(x, t) -> let set = fv t in StringSet.remove x set in set | Application(t1, t2) -> let set1 = fv t1 in let set2 = fv t2 in let unite = StringSet.union t1 t2 in unite;; let extract_some = function | Some x -> x let rec substitute x s = match s with | (s1, t) -> match t with | Variable(var) -> if x = var then s1 else t | Abstraction (var, t1) -> if x = var then t else let set = fv s1 in if StringSet.mem var set then let term_to_string = format_term_conv t1 in let unite = StringSet.union set term_to_string in let fresh = fresh_var unite in Abstraction (fresh, substitute x (s1, Abstraction (fresh, substitute var (fresh, t1)))) else Abstraction (var, substitute x (s1,t1)) | Application(t1, t2) -> Application (substitue x (s1, t1), substitue x (s1, t2));; let rec reduce_cbv = fun term -> match term with | Abstraction (x, t1) -> Some(term) | Application (t1, t2) -> match t2 with | Abstraction (var, t) -> reduce_cbn (substitute var (t2, t)) | Application (term1, term2) -> reduce_cbn t2 | _ -> None let rec reduce_cbn = fun term -> match term with | Abstraction (x, t1) -> Some(term) | Application (t1, t2) -> match t1 with | Abstraction (var, t) -> reduce_cbn (substitute var (t2, t)) | Application (term1, term2) -> reduce_cbn t1 | _ -> None