Guest User

Untitled

a guest
Jul 12th, 2013
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 12.83 KB | None | 0 0
  1. module U = struct
  2.   type expr =
  3.       Zero
  4.     | True
  5.     | False
  6.     | Id of string
  7.     | Pred of expr
  8.     | Succ of expr
  9.     | IsZero of expr
  10.     | Cons of expr * expr
  11.     | Car of expr
  12.     | Cdr of expr
  13.     | Nil
  14.     | Null of expr
  15.     | IfThenElse of expr * expr * expr
  16.     | Fun of string * expr
  17.     | Apply of expr * expr
  18.     | LetIn of string * expr * expr
  19.  
  20.   let rec string_of_expr = function
  21.     Zero -> "0"
  22.   | True -> "true"
  23.   | False -> "false"
  24.   | Id x -> x
  25.   | Pred x -> Printf.sprintf "pred %s" (string_of_expr x)
  26.   | Succ x -> Printf.sprintf "succ %s" (string_of_expr x)
  27.   | IsZero x -> Printf.sprintf "iszero %s" (string_of_expr x)
  28.   | Cons (a, b) -> Printf.sprintf "%s :: %s" (string_of_expr a)
  29.              (string_of_expr b)
  30.   | Car a -> Printf.sprintf "car %s" (string_of_expr a)
  31.   | Cdr a -> Printf.sprintf "cdr %s" (string_of_expr a)
  32.   | Nil -> "[]"
  33.   | Null a -> Printf.sprintf "null %s" (string_of_expr a)
  34.   | IfThenElse (a, b, c) ->
  35.       Printf.sprintf "if %s then %s else %s" (string_of_expr a)
  36.     (string_of_expr b) (string_of_expr c)
  37.   | Fun (x, a) ->
  38.       Printf.sprintf "fun %s -> %s" x (string_of_expr a)
  39.   | Apply (a, b) ->
  40.       Printf.sprintf "(%s %s)" (string_of_expr a)
  41.              (string_of_expr b)
  42.   | LetIn (x, a, b) ->
  43.       Printf.sprintf "let %s = %s in %s" x (string_of_expr a)
  44.              (string_of_expr b)
  45. end
  46.  
  47. module T = struct
  48.   type expr =
  49.       Zero
  50.     | True
  51.     | False
  52.     | Id of string
  53.     | Pred of typed_expr
  54.     | Succ of typed_expr
  55.     | IsZero of typed_expr
  56.     | Cons of typed_expr * typed_expr
  57.     | Car of typed_expr
  58.     | Cdr of typed_expr
  59.     | Nil
  60.     | Null of typed_expr
  61.     | IfThenElse of typed_expr * typed_expr * typed_expr
  62.     | Fun of string * typed_expr
  63.     | Apply of typed_expr * typed_expr
  64.     | LetIn of string * typed_expr * typed_expr
  65.  
  66.   and typed_expr =
  67.       Typed of node_type * expr
  68.  
  69.   and node_type =
  70.       Int
  71.     | Bool
  72.     | List of node_type
  73.     | Arrow of node_type * node_type
  74.     | TyVar of int
  75.  
  76.   let rec string_of_expr = function
  77.     Zero -> "0"
  78.   | True -> "true"
  79.   | False -> "false"
  80.   | Id x -> x
  81.   | Pred x -> Printf.sprintf "pred %s" (string_of_texpr x)
  82.   | Succ x -> Printf.sprintf "succ %s" (string_of_texpr x)
  83.   | IsZero x -> Printf.sprintf "iszero %s" (string_of_texpr x)
  84.   | Cons (a, b) -> Printf.sprintf "%s :: %s" (string_of_texpr a)
  85.              (string_of_texpr b)
  86.   | Car a -> Printf.sprintf "car %s" (string_of_texpr a)
  87.   | Cdr a -> Printf.sprintf "cdr %s" (string_of_texpr a)
  88.   | Nil -> "[]"
  89.   | Null a -> Printf.sprintf "null %s" (string_of_texpr a)
  90.   | IfThenElse (a, b, c) ->
  91.       Printf.sprintf "if %s then %s else %s" (string_of_texpr a)
  92.     (string_of_texpr b) (string_of_texpr c)
  93.   | Fun (x, a) ->
  94.       Printf.sprintf "fun %s -> %s" x (string_of_texpr a)
  95.   | Apply (a, b) ->
  96.       Printf.sprintf "(%s %s)" (string_of_texpr a)
  97.              (string_of_texpr b)
  98.   | LetIn (x, a, b) ->
  99.       Printf.sprintf "let %s = %s in %s" x (string_of_texpr a)
  100.              (string_of_texpr b)
  101.  
  102.   and string_of_texpr (Typed (t, x)) =
  103.     Printf.sprintf "(%s : %s)" (string_of_expr x) (string_of_type t)
  104.  
  105.   and string_of_type ?(bracket=false) = function
  106.     Int -> "int"
  107.   | Bool -> "bool"
  108.   | List x -> Printf.sprintf "%s list" (string_of_type x)
  109.   | Arrow (a, b) ->
  110.       if bracket then
  111.         Printf.sprintf "(%s -> %s)" (string_of_type ~bracket:true a)
  112.       (string_of_type b)
  113.       else
  114.         Printf.sprintf "%s -> %s" (string_of_type ~bracket:true a)
  115.       (string_of_type b)
  116.   | TyVar t -> Printf.sprintf "'t%d" t
  117. end
  118.  
  119. let rec find_subst subst_tab a =
  120.   try
  121.     find_subst subst_tab (Hashtbl.find subst_tab a)
  122.   with Not_found ->
  123.     a
  124.  
  125. let rec subst_tyvars subst = function
  126.     T.TyVar t -> T.TyVar (find_subst subst t)
  127.   | T.List t -> T.List (subst_tyvars subst t)
  128.   | T.Arrow (a, b) -> T.Arrow (subst_tyvars subst a, subst_tyvars subst b)
  129.   | x -> x
  130.  
  131. let resolve_type ht subst typ =
  132.   let open T in
  133.   let rec lookup t =
  134.     match t with
  135.       TyVar t1 ->
  136.         begin try
  137.       lookup (Hashtbl.find ht (find_subst subst t1))
  138.     with Not_found ->
  139.       TyVar (find_subst subst t1)
  140.     end
  141.     | List t -> List (lookup t)
  142.     | Arrow (a, b) -> Arrow (lookup a, lookup b)
  143.     | x -> x in
  144.   lookup typ
  145.  
  146. exception Type_mismatch of T.node_type * T.node_type
  147. exception Occurs_check of int * T.node_type
  148.  
  149. module IntSet = Set.Make (struct
  150.   type t = int
  151.   let compare = compare
  152. end)
  153.  
  154. let imply t =
  155.   let open T in
  156.   let i = ref 0 in
  157.   let new_typevar () = incr i; !i in
  158.   let new_type () = TyVar (new_typevar ()) in
  159.   let ht = Hashtbl.create 10
  160.   and subst = Hashtbl.create 10 in
  161.   let rec occurs_raw tyvar = function
  162.     Int | Bool -> false
  163.   | List t -> occurs_raw tyvar t
  164.   | Arrow (a, b) -> occurs_raw tyvar a || occurs_raw tyvar b
  165.   | TyVar tv -> tv = tyvar
  166.   and occurs tyvar typ =
  167.     occurs_raw (find_subst subst tyvar) (resolve_type ht subst typ)
  168.   and occurs_in_set tyvar tset =
  169.     IntSet.exists (fun typ -> occurs tyvar (TyVar typ)) tset
  170.   and add_subst a b =
  171.     if a <> b then begin
  172.       let lower = min a b
  173.       and higher = max a b in
  174.       if Hashtbl.mem subst higher then
  175.     unify (TyVar (Hashtbl.find subst higher)) (TyVar lower)
  176.       else
  177.     Hashtbl.add subst higher lower
  178.     end
  179.   and unify ?a ?b t1 t2 =
  180.     Printf.printf "%s === %s\n" (string_of_type t1)
  181.           (string_of_type t2);
  182.     begin match a with
  183.       None -> ()
  184.     | Some a -> Printf.printf "A: %s\n" (U.string_of_expr a)
  185.     end;
  186.     begin match b with
  187.       None -> ()
  188.     | Some a -> Printf.printf "B: %s\n" (U.string_of_expr a)
  189.     end;
  190.     match resolve_type ht subst t1, resolve_type ht subst t2 with
  191.       TyVar a, TyVar b when a <> b -> add_subst a b
  192.     | TyVar a, other
  193.     | other, TyVar a ->
  194.         let a' = find_subst subst a in
  195.     if occurs a' other then begin
  196.       Printf.printf "'t%d occurs in %s\n" a' (string_of_type other);
  197.       raise (Occurs_check (a', other))
  198.     end else if Hashtbl.mem ht a' then begin
  199.       let prevtype = Hashtbl.find ht a' in
  200.       Printf.printf "Unifying with previous for %d (%d) (%s / %s)\n" a' a
  201.         (string_of_type prevtype) (string_of_type other);
  202.       (* It's very important that here PREVTYPE and OTHER are not both
  203.          plain TyVars!  *)
  204.       unify prevtype other
  205.     end else
  206.       Hashtbl.add ht a' other
  207.     | Int, Int
  208.     | Bool, Bool -> ()
  209.     | List l1, List l2 -> unify l1 l2
  210.     | Arrow (a1, a2), Arrow (b1, b2) -> unify a1 b1; unify a2 b2
  211.     | t1, t2 -> raise (Type_mismatch (t1, t2)) in
  212.   let inst bound typ =
  213.     let newtvs = Hashtbl.create 5 in
  214.     let rec inst' typ =
  215.       match typ with
  216.     Int | Bool -> typ
  217.       | List t -> List (inst' t)
  218.       | Arrow (a, b) -> Arrow (inst' a, inst' b)
  219.       | TyVar tv ->
  220.           if not (occurs_in_set tv bound) then begin
  221.         if not (Hashtbl.mem newtvs tv) then
  222.           Hashtbl.add newtvs tv (new_typevar ());
  223.         TyVar (Hashtbl.find newtvs tv)
  224.       end else
  225.         typ in
  226.     inst' (resolve_type ht subst typ) in
  227.   let generalise ctx t =
  228.     let newtvs = Hashtbl.create 5 in
  229.     let res_type = resolve_type ht subst t in
  230.     let rec gen' t =
  231.       match t with
  232.         Int | Bool -> t
  233.       | List t -> List (gen' t)
  234.       | Arrow (a, b) -> Arrow (gen' a, gen' b)
  235.       | TyVar tv ->
  236.       if List.exists (fun (_, typ) -> occurs tv typ) ctx then begin
  237.         if not (Hashtbl.mem newtvs tv) then
  238.           Hashtbl.add newtvs tv (new_typevar ());
  239.         TyVar (Hashtbl.find newtvs tv)
  240.       end else
  241.         t in
  242.     gen' res_type in
  243.   let rec imply' ctx bound t =
  244.     try
  245.       match t with
  246.     U.Zero -> Typed (Int, Zero)
  247.       | U.True -> Typed (Bool, True)
  248.       | U.False -> Typed (Bool, False)
  249.       | U.Id x -> Typed (inst bound (List.assoc x ctx), Id x)
  250.       | U.Pred a ->
  251.       let Typed (ta, a') = imply' ctx bound a in
  252.       unify ~a:a ta Int;
  253.       Typed (Int, Pred (Typed (ta, a')))
  254.       | U.Succ a ->
  255.       let Typed (ta, a') = imply' ctx bound a in
  256.       unify ~a:a ta Int;
  257.       Typed (Int, Succ (Typed (ta, a')))
  258.       | U.IsZero a ->
  259.       let Typed (ta, a') = imply' ctx bound a in
  260.       unify ~a:a ta Int;
  261.       Typed (Bool, IsZero (Typed (ta, a')))
  262.       | U.Cons (a, b) ->
  263.           let Typed (ta, a') = imply' ctx bound a in
  264.       let Typed (tb, b') = imply' ctx bound b in
  265.       let nt = new_type () in
  266.       unify ~a:a nt ta;
  267.       unify (List nt) tb;
  268.       Typed (List nt, Cons (Typed (ta, a'), Typed (tb, b')))
  269.       | U.Car a ->
  270.           let Typed (ta, a') = imply' ctx bound a in
  271.       let nt = new_type () in
  272.       unify ~a:a ta (List nt);
  273.       Typed (nt, Car (Typed (ta, a')))
  274.       | U.Cdr a ->
  275.       let Typed (ta, a') = imply' ctx bound a in
  276.       let nt = new_type () in
  277.       unify ~a:a ta (List nt);
  278.       Typed (ta, Cdr (Typed (ta, a')))
  279.       | U.Nil ->
  280.       let nt = new_type () in
  281.           Typed (List nt, Nil)
  282.       | U.Null a ->
  283.       let Typed (ta, a') = imply' ctx bound a in
  284.       let nt = new_type () in
  285.       unify ~a:a ta (List nt);
  286.       Typed (Bool, Null (Typed (ta, a')))
  287.       | U.IfThenElse (a, b, c) ->
  288.       let Typed (ta, a') = imply' ctx bound a in
  289.       let Typed (tb, b') = imply' ctx bound b in
  290.       let Typed (tc, c') = imply' ctx bound c in
  291.       unify ~a:b ~b:c tb tc;
  292.       unify ~a:a ta Bool;
  293.       Typed (tb, IfThenElse (Typed (ta, a'), Typed (tb, b'),
  294.          Typed (tc, c')))
  295.       | U.Fun (x, a) ->
  296.       let vartype = new_typevar () in
  297.       let bound' = IntSet.add vartype bound in
  298.       let Typed (ta, a') = imply' ((x, TyVar vartype) :: ctx) bound' a in
  299.       Typed (Arrow (TyVar vartype, ta), Fun (x, Typed (ta, a')))
  300.       | U.Apply (a, b) ->
  301.       let Typed (ta, a') = imply' ctx bound a in
  302.       let Typed (tb, b') = imply' ctx bound b in
  303.       let nt1 = new_type () in
  304.       unify ~a:a ~b:b ta (Arrow (tb, nt1));
  305.       Typed (nt1, Apply (Typed (ta, a'), Typed (tb, b')))
  306.       | U.LetIn (x, a, b) ->
  307.           let Typed (ta, a') = imply' ctx bound a in
  308.       Printf.printf "ta = %s\n" (string_of_type (resolve_type ht subst ta));
  309.       let vartype = generalise ctx ta in
  310.       Printf.printf "ta (gen) = %s\n" (string_of_type vartype);
  311.       let addvar = (x, vartype) :: ctx in
  312.       let Typed (tb, b') = imply' addvar bound b in
  313.       Printf.printf "tb = %s\n" (string_of_type tb);
  314.       Typed (tb, LetIn (x, Typed (ta, a'), Typed (tb, b')))
  315.     with Occurs_check (tv, typ) ->
  316.       Printf.printf "when unifying %s\n" (U.string_of_expr t);
  317.       failwith "Stop."
  318.     in
  319.   let typed_expr = imply' [] IntSet.empty t in
  320.   typed_expr, ht, subst
  321.  
  322. let rec rewrite_types ht subst typed_expr =
  323.   let open T in
  324.   let Typed (t1, expr) = typed_expr in
  325.   let expr' =
  326.     match expr with
  327.       Zero | True | False | Id _ | Nil -> expr
  328.     | Pred x -> Pred (rewrite_types ht subst x)
  329.     | Succ x -> Succ (rewrite_types ht subst x)
  330.     | IsZero x -> IsZero (rewrite_types ht subst x)
  331.     | Cons (x, y) -> Cons (rewrite_types ht subst x, rewrite_types ht subst y)
  332.     | Car x -> Car (rewrite_types ht subst x)
  333.     | Cdr x -> Cdr (rewrite_types ht subst x)
  334.     | Null x -> Null (rewrite_types ht subst x)
  335.     | IfThenElse (a, b, c) -> IfThenElse (rewrite_types ht subst a,
  336.                       rewrite_types ht subst b,
  337.                       rewrite_types ht subst c)
  338.     | Fun (x, a) -> Fun (x, rewrite_types ht subst a)
  339.     | Apply (a, b) -> Apply (rewrite_types ht subst a, rewrite_types ht subst b)
  340.     | LetIn (x, a, b) -> LetIn (x, rewrite_types ht subst a,
  341.                 rewrite_types ht subst b) in
  342.   Typed (resolve_type ht subst t1, expr')
  343.  
  344. let doit expr =
  345.   try
  346.     let typed, ht, subst = imply expr in
  347.     Hashtbl.iter
  348.       (fun i t ->
  349.     Printf.printf "Mapping for 't%d = %s\n" i (T.string_of_type t)) ht;
  350.     Hashtbl.iter
  351.       (fun i t ->
  352.     Printf.printf "Substitution 't%d = 't%d\n" i t) subst;
  353.     Hashtbl.iter
  354.       (fun i t ->
  355.     Printf.printf "Subst map for 't%d = %s\n" i
  356.       (T.string_of_type (subst_tyvars subst t))) ht;
  357.     rewrite_types ht subst typed
  358.   with Type_mismatch (a, b) ->
  359.     Printf.fprintf stderr "Type mismatch (%s vs %s)\n" (T.string_of_type a)
  360.            (T.string_of_type b);
  361.     flush stderr;
  362.     failwith "stop."
  363.  
  364. let typeof (T.Typed (t, _)) = t
  365.  
  366. let degen =
  367.   let open U in
  368.   LetIn ("pair", Fun ("x", Fun ("y", Fun ("z",
  369.            Apply (Apply (Id "z", Id "x"), Id "y")))),
  370.   LetIn ("x1", Fun ("y", Apply (Apply (Id "pair", Id "y"), Id "y")),
  371.     LetIn ("x2", Fun ("y", Apply (Id "x1", Apply (Id "x1", Id "y"))),
  372.       LetIn ("x3", Fun ("y", Apply (Id "x2", Apply (Id "x2", Id "y"))),
  373.         LetIn ("x4", Fun ("y", Apply (Id "x3", Apply (Id "x3", Id "y"))),
  374.       Apply (Id "x4", Fun ("z", Id "z")))))))
  375.  
  376. let degen2 =
  377.   let open U in
  378.   LetIn ("pair", Fun ("x", Fun ("y", Fun ("z",
  379.            Apply (Apply (Id "z", Id "x"), Id "y")))),
  380.   LetIn ("x1", Fun ("y", Apply (Apply (Id "pair", Id "y"), Id "y")),
  381.     Fun ("y", Apply (Id "x1", Apply (Id "x1", Id "y")))))
  382.  
  383. let expr1 =
  384.   let open U in
  385.   LetIn ("z", Zero, LetIn ("x", Fun ("y", Id "z"),
  386.     Cons (Apply (Id "x", False), Cons (Apply (Id "x", Zero), Nil))))
  387.  
  388. let expr2 =
  389.   let open U in
  390.   Fun ("z", LetIn ("x", Id "z", Cons (Id "z", Cons (Id "x", Nil))))
  391.  
  392. let _ =
  393.   doit degen2
Advertisement
Add Comment
Please, Sign In to add comment