Skip to content

Commit

Permalink
Add support for type rec over types with type parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
polytypic committed Jan 4, 2020
1 parent 4d637cd commit ab1a95b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 15 deletions.
53 changes: 38 additions & 15 deletions elab.ml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ and paths_row ta ps = function
ts1 @ ts2


let rec_from_extyp typ label s =
match s with
| ExT([], t) ->
let rec find_rec = function
| AppT(t, ts) ->
let rec_t, unroll_t, roll_t, ak = find_rec t in
rec_t, AppT(unroll_t, ts), AppT(roll_t, ts), ak
| RecT(ak, unroll_t) as rec_t ->
rec_t, unroll_t, rec_t, ak
| _ ->
error typ.at ("non-recursive type for " ^ label ^ ":\n"
^ " " ^ Types.string_of_extyp s) in
find_rec t
| _ ->
error typ.at ("non-recursive type for " ^ label ^ ":\n"
^ " " ^ Types.string_of_extyp s)


(* Instantiation *)

let rec instantiate env t e =
Expand Down Expand Up @@ -386,15 +404,18 @@ Trace.debug (lazy ("[FunE] env =" ^ VarSet.fold (fun a s -> s ^ " " ^ a) (domain

| EL.RollE(var, typ) ->
let s, zs1 = elab_typ env typ l in
let t, ak, t' =
match s with
| ExT([], (RecT(ak, t') as t)) -> t, ak, t'
| _ -> error typ.at "non-recursive type for rolling" in
let rec_t, unroll_t, roll_t, ak = rec_from_extyp typ "rolling" s in
let var_t = lookup_var env var in
let unroll_t = subst_typ (subst [ak] [rec_t]) unroll_t in
let _, zs2, f =
try sub_typ env (lookup_var env var) (subst_typ (subst [ak] [t]) t') []
with Sub e -> error var.at ("rolled value does not match annotation") in
ExT([], t), Pure, zs1 @ zs2,
IL.RollE(IL.AppE(f, IL.VarE(var.it)), erase_typ t)
try sub_typ env var_t unroll_t []
with Sub e ->
error var.at ("rolled value does not match annotation:\n"
^ " " ^ Types.string_of_typ var_t ^ "\n"
^ "vs\n"
^ " " ^ Types.string_of_typ unroll_t) in
ExT([], roll_t), Pure, zs1 @ zs2,
IL.RollE(IL.AppE(f, IL.VarE(var.it)), erase_typ roll_t)

| EL.IfE(var, exp1, exp2, typ) ->
let t0, zs0, ex = elab_instvar env var in
Expand Down Expand Up @@ -488,13 +509,15 @@ Trace.debug (lazy ("[UnwrapE] s2 = " ^ string_of_norm_extyp s2));

| EL.UnrollE(var, typ) ->
let s, zs1 = elab_typ env typ l in
let t, ak, t' =
match s with
| ExT([], (RecT(ak, t') as t)) -> t, ak, t'
| _ -> error typ.at "non-recursive type for rolling" in
let _, zs2, f = try sub_typ env (lookup_var env var) t [] with Sub e ->
error var.at ("unrolled value does not match annotation") in
ExT([], subst_typ (subst [ak] [t]) t'), Pure, zs1 @ zs2,
let rec_t, unroll_t, roll_t, ak = rec_from_extyp typ "unrolling" s in
let var_t = lookup_var env var in
let _, zs2, f = try sub_typ env var_t roll_t [] with Sub e ->
error var.at ("unrolled value does not match annotation:\n"
^ " " ^ Types.string_of_typ var_t ^ "\n"
^ "vs\n"
^ " " ^ Types.string_of_typ roll_t) in
let unroll_t = subst_typ (subst [ak] [rec_t]) unroll_t in
ExT([], unroll_t), Pure, zs1 @ zs2,
IL.UnrollE(IL.AppE(f, IL.VarE(var.it)))

| EL.RecE(var, typ, exp1) ->
Expand Down
65 changes: 65 additions & 0 deletions regression.1ml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,68 @@ Equivalence: {
symmetry 'a 'b (eq: t a b) : t b a =
wr (fun (type p _) => un eq (fun (type b) => type p b -> p a) id);
};

Hungry = {
type eat a = rec eat_a => a -> eat_a;

eater 'a: eat a = rec (eater: eat a) => @(eat a) (fun a => eater);

(<+) eater x = eater.@(eat _) x;

do eater <+ 1 <+ 2;
};

PolyRec = {
type l a = rec (type t) => alt a t;
t = rec (type t a) => fun (type a) => alt a (t (type (a, a)));

t_int = t int;

hmm (x: t int) = casealt (x.@(t int));

t0 = @(t int) (right (@(t (type (int, int))) (left (0, 0))));
};

N :> {
type Z;
type S _;
} = {
type Z = {};
type S _ = {};
};

ListN = let
type I (type x) (type p _ _) (type t _ _) = {
nil : p x N.Z;
(::) 'n : x -> t x n -> p x (N.S n);
};
type T x n (type t _ _) = (type p _ _) => I x p t -> p x n;
in {
t = rec (type t _ _) => fun (type x) (type n) => type wrap T x n t;

case 'x 'n (p: {type t _ _}) (cs: I x p.t t) e =
(unwrap e.@(t _ _): wrap T x n t) p.t cs;

local
mk 'x 'n (c: T x n t) = @(t x n) (wrap c: wrap T x n t);
in
nil 'x = mk (fun (type p _ _) (r: I x p t) => r.nil);
(::) 'x 'n (v: x) (vs: t x n) = mk (fun (type p _ _) (r: I x p t) => r.:: v vs);
end;
} :> {
type t _ _;

case 'x 'n: (p: {type t _ _}) => I x p.t t => t x n -> p.t x n;

nil 'x : t x N.Z;
(::) 'x 'n : x => t x n => t x (N.S n);
};

ListN = {
...ListN;
map 'x 'y 'n (xy: x -> y) = rec (map: 'n => t x n -> t y n) =>
case {type t _ n = t y n} {
nil = nil;
(::) x xs = xy x :: map xs;
};
};

0 comments on commit ab1a95b

Please sign in to comment.