Advertisement
Guest User

Untitled

a guest
Nov 26th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 7.36 KB | None | 0 0
  1. (* λ calculus, with Forall and simple types *)
  2.  
  3. type 'a binding =
  4.   | SymBind of 'a
  5.   | QuantifierBind
  6.  
  7. type 'a context = (string * 'a binding) list
  8.  
  9. type typ =
  10.   | UnitTy
  11.   | IntTy
  12.   | Arrow of typ * typ
  13.   | Forall of string * typ
  14.   | ClosureTy of (typ context) * typ
  15.   | SymbolTy of string
  16.  
  17. type expr =
  18.   | Closure of (expr context) * expr
  19.   | Unit
  20.   | Symbol of string
  21.   | Int of int
  22.   | Lam of string * typ * expr  (* turns into Arrow. Takes expr as argument, returns expr *)
  23.   | App of expr * expr
  24.   | TLam of string * expr       (* expr version of Forall. Takes typ as argument, returns expr *)
  25.   | TApp of expr * typ
  26.  
  27. let rec lookup context key =
  28.   match context with
  29.   | [] -> Error "No result"
  30.   | (k, QuantifierBind) :: rest -> lookup rest key
  31.   | (k, SymBind v) :: rest -> if key = k
  32.                               then Ok v
  33.                               else lookup rest key
  34.  
  35. let str = String.concat ""
  36.  
  37. let rec string_of_typ t = match t with
  38.   | UnitTy -> "UnitTy"
  39.   | IntTy -> "IntTy"
  40.   | Arrow _ -> "Arrow"
  41.   | Forall (s, t) -> str ["Forall "; s; " "; string_of_typ t]
  42.   | ClosureTy (_ctx, t) -> str ["Closure "; string_of_typ t]
  43.   | SymbolTy s -> str ["SymbolTy "; s]
  44.  
  45. let string_of_expr e = match e with
  46.   | Unit -> "Unit"
  47.   | Closure _ -> "Closure"
  48.   | Symbol s -> str ["Symbol "; s]
  49.   | Int i -> str ["Int "; string_of_int i]
  50.   | Lam _ -> "Lam"
  51.   | App _ -> "App"
  52.   | TLam _ -> "TLam"
  53.   | TApp _ -> "TApp"
  54.  
  55. let rec convert_context converter_fn original_context exprcontext acc =
  56.   (* カリたべたい *)
  57.   let convert_context = convert_context converter_fn original_context in
  58.   match exprcontext with
  59.   | [] -> acc
  60.   | (x, QuantifierBind) :: rest ->
  61.      convert_context rest ((x, QuantifierBind) :: acc)
  62.   | (x, SymBind e) :: rest ->
  63.      (match converter_fn original_context e with
  64.       | Ok t -> convert_context rest ((x, SymBind t) :: acc)
  65.       | Error e -> failwith (str ["typ_context error: "; e]))
  66.  
  67. let rec typ_of_expr context e =
  68.   match e with
  69.   | Unit -> Ok UnitTy
  70.   | Int i -> Ok IntTy
  71.   | Closure (ctx, e) ->
  72.      let new_context = convert_context typ_of_expr context ctx context in
  73.      typ_of_expr new_context e
  74.   | Symbol s -> lookup context s
  75.   | Lam (x, in_typ, body) ->
  76.      (let new_context = (x, SymBind in_typ) :: context in
  77.       match typ_of_expr new_context body with
  78.       | Ok return_typ -> Ok (Arrow (in_typ, return_typ))
  79.       | Error e -> Error (str [ "Error finding return type of lambda. Error: "
  80.                               ; e]))
  81.   | App (e0,
  82.          e1) ->
  83.      (match (typ_of_expr context e0,
  84.              typ_of_expr context e1) with
  85.       | (Ok (Arrow (t0_0, t0_1)),
  86.          Ok t1) -> if t1 = t0_0
  87.                    then Ok t0_1
  88.                    else Error (str ["Type mismatch"])
  89.       | (Ok (ClosureTy (ctx, Arrow (t0_0, t0_1))),
  90.          Ok t1) -> if t1 = t0_0
  91.                    then Ok t0_1
  92.                    else Error
  93.                           (str
  94.                              ["Type mismatch. t0_0: "
  95.                              ;string_of_typ t0_0
  96.                              ;", t0_1: "
  97.                              ;string_of_typ t0_1
  98.                              ;", t1: "
  99.                              ;string_of_typ t1
  100.                              ])
  101.       | (Ok t, _) -> Error (str ["Not given a lambda as first thing to App. "
  102.                                 ;string_of_typ t])
  103.       | _ -> Error (str ["Error getting typ of expr App"]))
  104.   | TLam (a, body) ->
  105.      (let new_context = (a, QuantifierBind) :: context in
  106.       match typ_of_expr new_context body with
  107.       | Ok body_type -> Ok (ClosureTy (new_context,
  108.                                        Forall (a,
  109.                                                body_type)))
  110.       | Error e -> Error (str [ "Failed to get typ of TLam, and thus can not construct Forall. Error: "
  111.                               ; e]))
  112.   | TApp (TLam (a, body),
  113.           t1) -> let new_context = (a, QuantifierBind) :: context in
  114.                  typ_of_expr new_context body
  115.   | TApp (e0, t1) ->
  116.      (match typ_of_expr context e0 with
  117.       | Ok (ClosureTy (ctx,
  118.                        Forall (a, body))) ->
  119.          let new_context = (a, SymBind t1) :: ctx @ context in
  120.          Ok (ClosureTy (new_context,
  121.                         body))
  122.       | Ok (ClosureTy(ctx,
  123.                       t)) ->
  124.          Error (str ["TApp given ClosureTy with non-forall on left-hand-side. IS: "
  125.                     ;string_of_typ t])
  126.       | Ok (Forall (a, body)) -> Error "TApp given naked Forall as first argument"
  127.       | Ok _ -> Error "TApp given non-Forall first argument"
  128.       | Error e -> Error (str ["Error in TApp - error: "
  129.                               ;e]))
  130.  
  131. let rec eval context e =
  132.     let context: (expr context) = context in
  133.     match e with
  134.     | Unit -> Ok Unit
  135.     | Closure (ctx, e) -> eval (List.append ctx context) e
  136.     | Int i -> Ok (Int i)
  137.     | Lam (x, t, body) -> Ok (Closure (context,
  138.                                        Lam (x, t, body)))
  139.     | Symbol s -> lookup context s
  140.     | App (Closure(ctx,
  141.                    Lam (x, t, body)),
  142.            e1) -> let new_context = (x, SymBind e1) :: ctx @ context in
  143.                   eval new_context body
  144.     | App (e0, e1) -> (match eval context e0 with
  145.                        | Ok (Closure (ctx,
  146.                                       Lam (x, t, body))) ->
  147.                           eval (ctx @ context) (App (Lam (x,
  148.                                                   t,
  149.                                                   body),
  150.                                              e1))
  151.                        | Ok _ -> Error "Can't apply non-Lam"
  152.                        | Error e -> Error (str ["Apply error: "
  153.                                                ;e]))
  154.     | TLam (a, body) -> Ok (TLam (a, body))
  155.     | TApp (TLam (a, body),
  156.             given_typ) -> let new_context = (a, QuantifierBind) :: context in
  157.                           eval new_context body
  158.     | TApp (e0, t) -> (match eval context e0 with
  159.                        | Ok (TLam (a, body)) -> let _ = failwith "Not gonna happen" in
  160.                                                 eval context (TApp (TLam (a, body), t))
  161.                        | Ok (Closure (ctx,
  162.                                       TLam (a,
  163.                                             body))) ->
  164.                           eval (ctx @ context) body
  165.                        | Ok _ -> Error "Can't type-apply non-Λ"
  166.                        | Error e -> Error (str [ "Error applying type lambda. Error: "
  167.                                                ; e]))
  168.  
  169. let tlam a body = TLam (a, body)
  170. let lam x t body = Lam (x, t, body)
  171. let app e0 e1 = App (e0, e1)
  172. let tapp e0 tyT1 = TApp (e0, tyT1)
  173. ;; eval [] (tlam "a" (lam "x"
  174.                         (SymbolTy "a")
  175.                         (Symbol "x")))
  176.  
  177. let k_combinator = (tlam "a" (tlam "_b"
  178.                                 (lam
  179.                                    "x"
  180.                                    (SymbolTy "a")
  181.                                    (lam
  182.                                       "_y"
  183.                                       (SymbolTy "_b")
  184.                                       (Symbol "x")))))
  185.  
  186. let k_intint = (TApp (TApp (k_combinator,
  187.                             IntTy),
  188.                       IntTy))
  189.  
  190. (* forall a b . a -> b -> a *)
  191. ;; typ_of_expr [] (app k_intint (Int 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement