Implementación O’Caml del Sistema de Tipos para el λ-Cálculo con booleanos Programación Funcional 1. Representación de Tipos y Expresiones type variable = string;; type booleano = F | V;; type tipo = Bool | Flecha of tipo * tipo;; type term = | | | | 2. Cons Var Abs App Cnd of of of of of booleano variable variable * tipo * term term * term term * term * term;; Pretty-printer de Tipos y Expresiones let rec pretty_tipo = function Bool -> "Bool" | Flecha (m,n) -> "(" ^ pretty_tipo m ^ " -> " ^ pretty_tipo n ^ ")";; let rec pretty_term = function Cons V -> "true" | Cons F -> "false" | Var x -> x | Abs (x,t,m) -> "(\\" ^ x ^ ":" ^ pretty_tipo t ^ "." ^ pretty_term m ^ ")" | App (m,n) -> "(" ^ pretty_term m ^ " " ^ pretty_term n ^ ")" | Cnd (g,t,e) -> "(if " ^ pretty_term g ^ " then " ^ pretty_term t ^ " else " ^ pretty_term e ^ ")";; 1 3. Representación de Contextos type contexto = (variable * tipo) list;; let contexto_vacio = [];; let aniade (v,t) contexto = (v,t) :: contexto;; 4. Tipo de una Variable en un Contexto exception No_ligada of string;; let rec tipo_de_variable contexto x = match contexto with (y,t)::_ when x=y -> t | _ :: contexto’ -> tipo_de_variable contexto’ x | _ -> raise (No_ligada x);; 5. Algoritmo de Tipado exception Type_error of string;; let rec tipar contexto = function Cons _ -> Bool | Var x -> tipo_de_variable contexto x | App (f,x) -> let t1 = tipar contexto f and t2 = tipar contexto x in (match t1 with Flecha(t,s) when t=t2 -> s | Flecha(t,s) -> raise (Type_error ("El tipo de " ^ pretty_term x ^ " es " ^ pretty_tipo t2 ^ " y no concuerda con " ^ pretty_tipo t)) | _ -> raise (Type_error (pretty_term f ^ ": " ^ pretty_tipo t1 ^ " no es una función"))) | Abs (x,t,m) -> Flecha (t, tipar (aniade (x,t) contexto) m) | Cnd (g,t,e) -> match (tipar contexto g) with Bool -> let t1 = tipar contexto t 2 and t2 = tipar contexto e in if t1 = t2 then t1 else raise (Type_error ("La rama then tiene tipo " ^ pretty_tipo t1 ^ " mientras que la rama else es " ^ pretty_tipo t2 ^ " en " ^ pretty_term (Cnd(g,t,e)))) | nobool -> raise (Type_error ("La guardia de " ^ pretty_term (Cnd(g,t,e)) ^ " no es booleana, sino de tipo " ^ pretty_tipo nobool));; 6. Ejemplos de Expresiones let e1 = Abs ("x", Bool, Cnd (Var "x", Cons F, Cons V));; let e2 = Abs ("x", Bool, Abs ("y", Bool, Cnd (Var "x", Var "y", Cons F)));; let e3 = Abs ("f", Flecha(Bool,Bool), Abs("x", Bool, App(Var "f", App(Var "f", Var "x"))));; let e4 = App (Var "f", Cons V);; let e5 = App( Abs( "f", Flecha(Bool,Bool), App (Var "f", Cons F)), Cons V);; let e6 = App (Cons V, Cons F);; let e7 = Cnd (Abs ("x",Bool,Var "x"), Cons V, Cons F);; let e8 = Cnd (Cons V, Cons F, Abs("x", Bool, Var "x"));; 7. Tipado de los Ejemplos # pretty_tipo (tipar contexto_vacio e1);; - : string = "(Bool -> Bool)" 3 # pretty_tipo (tipar contexto_vacio e2);; - : string = "(Bool -> (Bool -> Bool))" # pretty_tipo (tipar contexto_vacio e3);; - : string = "((Bool -> Bool) -> (Bool -> Bool))" # pretty_tipo (tipar contexto_vacio e4);; Uncaught exception: No_ligada("f") # pretty_tipo (tipar contexto_vacio e5);; Uncaught exception: Type_error("El tipo de true es Bool y no concuerda con (Bool -> Bool)") # pretty_tipo (tipar contexto_vacio e6);; Uncaught exception: Type_error("true: Bool no es una función") # pretty_tipo (tipar contexto_vacio e7);; Uncaught exception: Type_error("La guardia de (if (\\x:Bool.x) then true else false) no es booleana, sino de tipo (Bool -> Bool)") # pretty_tipo (tipar contexto_vacio e8);; Uncaught exception: Type_error("La rama then tiene tipo Bool mientras que la rama else es (Bool -> Bool) en (if true then false else (\\x:Bool.x))") 4