Advertisement
Guest User

Untitled

a guest
Oct 13th, 2019
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. external val print : string -> unit = "print"
  2.  
  3. type var <- string
  4.  
  5. type expr =
  6.   | Ref of var
  7.   | App of expr * expr
  8.   | Lam of var  * expr
  9.   | Lit of int
  10.   | Pair of expr * expr
  11.  
  12. let show_expr = function
  13.   | Ref x -> x
  14.   | App (f, x) -> "(" ^ show_expr f ^ ") (" ^ show_expr x ^ ")"
  15.   | Lam (v, x) -> "fun " ^ v ^ ". " ^ show_expr x
  16.   | Lit x -> tostring x
  17.   | Pair (a, b) -> "(" ^ show_expr a ^ ", " ^ show_expr b ^ ")"
  18.  
  19. let f :$  x = App (f, x)
  20. let v :-> x = Lam (v, x)
  21.  
  22. type value =
  23.   | Closure of value -> value
  24.   | Free_var of var
  25.   | Int of int
  26.   | Tup of value * value
  27.  
  28. let eval context = function
  29.   | Ref v ->
  30.     match find (fun (x, _) -> x == v) context with
  31.     | Some (_, vl) -> vl
  32.     | None -> Free_var v
  33.   | Lam (name, body) ->
  34.     Closure @@ fun argument ->
  35.       eval ((name, argument) :: context) body
  36.   | App (f, x) ->
  37.     match eval context f with
  38.     | Closure lambda -> lambda (eval context x)
  39.   | Lit x ->
  40.     Int x
  41.   | Pair (x, y) ->
  42.     Tup (eval context x, eval context y)
  43.  
  44. type ty =
  45.   | Tv of var * ref (option ty)
  46.   | Fn of ty * ty
  47.   | Int_t
  48.   | Tup_t of ty * ty
  49.  
  50. type context <- list (var * ty)
  51. type problem <- list (ty * ty)
  52.  
  53. let fresh_type =
  54.   let counter = ref 0
  55.   fun () ->
  56.     counter := !counter + 1
  57.     Tv ("t" ^ tostring !counter, ref None)
  58.  
  59. let infer (context : context) expression : either string (ty * problem) =
  60.   let open Either
  61.   match expression with
  62.   | Ref v ->
  63.     match find (fun (x, _) -> x == v) context with
  64.     | Some (_, t) -> Right (t, [])
  65.     | None        -> Left ("variable not in scope: " ^ v)
  66.   | App (fn, arg) -> begin
  67.       with (fn_t, fn_q)   <- infer context fn
  68.       with (arg_t, arg_q) <- infer context arg
  69.       let res_t = fresh_type ()
  70.       Right (res_t, (fn_t, Fn (arg_t, res_t)) :: fn_q ++ arg_q)
  71.     end
  72.   | Lam (v, body) -> begin
  73.       let arg_t = fresh_type ()
  74.       with (t, q) <- infer ((v, arg_t) :: context) body
  75.       Right (Fn (arg_t, t), q)
  76.     end
  77.   | Lit _ ->
  78.     Right (Int_t, [])
  79.   | Pair (x, y) -> begin
  80.       with (x_t, _) <- infer context x
  81.       with (y_t, _) <- infer context y
  82.       Right (Tup_t (x_t, y_t), [])
  83.     end
  84.  
  85. let ftv = function
  86.   | Tv (v, _) -> [v]
  87.   | Fn (x, y) -> ftv x ++ ftv y
  88.   | Int_t -> []
  89.   | Tup_t (x, y) -> ftv x ++ ftv y
  90.  
  91. let unify a b =
  92.   match a, b with
  93.   | Int_t, Int_t -> Right ()
  94.   | Int_t, Fn _ -> Left "can't match integer with function type"
  95.   | Fn _, Int_t -> Left "can't match integer with function type"
  96.   | Tv (a, contents), ty ->
  97.     match !contents with
  98.     | Some tau -> unify tau ty
  99.   | Fn (a, b), Fn (c, d) -> begin
  100.       match unify a c with
  101.       | Right _ ->
  102.         match unify b d with
  103.         | Right _ -> Right ()
  104.         | _ -> Left "can't match functions"
  105.       | _ -> Left "can't match functions"
  106.     end
  107.   | Tup_t (a, b), Tup_t (c, d) -> begin
  108.       match unify a c with
  109.       | Right _ ->
  110.         match unify b d with
  111.         | Right _ -> Right ()
  112.         | _ -> Left "can't match tuples"
  113.       | _ -> Left "can't match tuples"
  114.     end
  115. and solve = function
  116.   | [] -> Right ()
  117.   | Cons ((a, b), xs) -> Either.( unify a b >>= fun _ -> solve xs )
  118.  
  119. let free_in v t =
  120.   match find (== v) (ftv t) with
  121.   | Some _ -> true
  122.   | None -> false
  123.  
  124. let norm_ty = function
  125.   | Tv (v, contents) -> Option.fold norm_ty (Tv (v, ref None)) !contents
  126.   | Fn (a, b) -> Fn (norm_ty a, norm_ty b)
  127.   | Int_t -> Int_t
  128.   | Tup_t (a, b) -> Tup_t (norm_ty a, norm_ty b)
  129.  
  130. let display_ty = function
  131.   | Fn (x, b) -> paren_fn x ^ " -> " ^ display_ty b
  132.   | Tup_t (a, b) -> "(" ^ display_ty a ^ ", " ^ display_ty b ^ ")"
  133.   | Int_t -> "int"
  134.   | Tv (v, _) -> v
  135. and paren_fn = function
  136.   | Fn _ as t -> "(" ^ display_ty t ^ ")"
  137.   | x -> display_ty x
  138.  
  139. let type_check expr =
  140.   let open Either in
  141.   fold (fun x -> x) (fun x -> x) @@
  142.     begin
  143.       with (ty, qs) <- infer [] expr
  144.       with _ <- solve qs
  145.       Right (display_ty (norm_ty ty))
  146.     end
  147.  
  148. let () =
  149.   let id = "x" :-> Ref "x"
  150.   let x = Ref "x"
  151.   print @@ show_expr id
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement