Skip to content

Commit 9a7f7e2

Browse files
committed
WIP Add derived form for datatypes
1 parent 2550a0b commit 9a7f7e2

File tree

11 files changed

+431
-65
lines changed

11 files changed

+431
-65
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
NAME = 1ml
66
MODULES = \
7-
lib source prim syntax parser lexer \
8-
fomega types iL env erase trace sub import elab \
7+
lib source prim fomega types env syntax \
8+
parser lexer iL erase trace sub import elab \
99
lambda compile \
1010
main
1111
NOMLI = syntax iL main import

elab.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ Trace.debug (lazy ("[RecT] t = " ^ string_of_norm_typ t));
599599
ExT([], t), Pure, lift_warn exp.at t env (zs1 @ zs2 @ zs3),
600600
IL.LetE(e, "_", materialize_typ t)
601601
)
602+
602603
| EL.ImportE(path) ->
603604
(match Import.resolve (Source.at_file path) path.it with
604605
| None -> Source.error path.at ("\""^path.it^"\" does not resolve to a file")
@@ -613,6 +614,9 @@ Trace.debug (lazy ("[RecT] t = " ^ string_of_norm_typ t));
613614
in
614615
elab_exp env exp l
615616

617+
| EL.WithEnvE (toExp) ->
618+
elab_exp env (toExp env) l
619+
616620
(*
617621
rec (X : (b : type) => {type t; type u a}) fun (b : type) => {type t = (X int.u b, X bool.t); type u a = (a, X b.t)}
618622
s1 = ?Xt:*->*, Xu:*->*->*. !b:*. [= b] -> {t : [= Xt b], u : !a:*. [= a] => [= Xu b a]}

examples/fc.1ml

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,14 @@ local import "prelude"
99
;; clarity.
1010

1111
GADTs = {
12-
Exp = {
13-
local
14-
type I (type t _) = {
15-
type case _
16-
Zero : case int
17-
Succ : t int ~> case int
18-
Pair 'a 'b : t a ~> t b ~> case (a, b)
19-
}
20-
...rec {type t _} => {type t a = wrap (m: I t) ~> m.case a}
21-
I = I t
22-
t
23-
case (m: I) (e: t _) = e m
24-
Zero : t _ = fun (m: I) => m.Zero
25-
Succ x : t _ = fun (m: I) => m.Succ x
26-
Pair l r : t _ = fun (m: I) => m.Pair l r
12+
Exp = data case t _ :> {
13+
Zero : case int
14+
Succ : t int ~> case int
15+
Pair 'a 'b : t a ~> t b ~> case (a, b)
2716
}
2817

2918
eval = rec (eval 'a: Exp.t a ~> a) =>
30-
Exp.case {
31-
type case x = x
19+
Exp.case (type fun x => x) {
3220
Zero = 0
3321
Succ x = eval x + 1
3422
Pair l r = (eval l, eval r)

examples/hoas.1ml

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,13 @@ local import "prelude"
55
;;
66
;; https://github.com/palladin/idris-snippets/blob/master/src/HOAS.idr
77

8-
let
9-
type I (type case _) (type t _) = {
10-
Val 'x : x ~> case x
11-
Bin 'x 'y 'z : (x ~> y ~> z) ~> t x ~> t y ~> case z
12-
If 'x : t Bool.t ~> t x ~> t x ~> case x
13-
App 'x 'y : t (x ~> y) ~> t x ~> case y
14-
Lam 'x 'y : (t x ~> t y) ~> case (x ~> y)
15-
Fix 'x 'y : t ((x ~> y) ~> x ~> y) ~> case (x ~> y)
16-
}
17-
type J (type t _) = {type case _, ...I case t}
18-
type T (type t _) x = (c: J t) ~> c.case x
19-
...{
20-
...rec {type t _} => {type t x = wrap T t x}
21-
case 'x (type case _) (cs: I case t) (e: t _) = e {case, ...cs}
22-
mk (fn: T t _) = fn
23-
} :> {
24-
type t _
25-
case 'x: (type case _) -> I case t -> t x ~> case x
26-
mk 'x: T t x -> t x
27-
}
28-
J = J t
29-
in {
30-
t, case
31-
Val 'x (v: x) = mk fun (e: J) => e.Val v
32-
Bin 'x 'y 'z (f: x ~> y ~> z) (l: t x) (r: t y) = mk fun (e: J) => e.Bin f l r
33-
If 'x (b: t Bool.t) (c: t x) (a: t x) = mk fun (e: J) => e.If b c a
34-
App 'x 'y (f: t (x ~> y)) (a: t x) = mk fun (e: J) => e.App f a
35-
Lam 'x 'y (f: t x ~> t y) = mk fun (e: J) => e.Lam f
36-
Fix 'x 'y (f: t ((x ~> y) ~> x ~> y)) = mk fun (e: J) => e.Fix f
8+
data case t _ :> {
9+
Val 'x : x ~> case x
10+
Bin 'x 'y 'z : (x ~> y ~> z) ~> t x ~> t y ~> case z
11+
If 'x : t Bool.t ~> t x ~> t x ~> case x
12+
App 'x 'y : t (x ~> y) ~> t x ~> case y
13+
Lam 'x 'y : (t x ~> t y) ~> case (x ~> y)
14+
Fix 'x 'y : t ((x ~> y) ~> x ~> y) ~> case (x ~> y)
3715
}
3816

3917
Fact = Fix <| Lam fun f => Lam fun x =>

examples/tiv.1ml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
local import "prelude"
2+
3+
;; As 1ML is powerful enough to encode GADTs we can define a value independent
4+
;; type representation or a deep embedding of type constructors.
5+
6+
type iso a b = {to: a ~> b, from: b ~> a}
7+
8+
Rep = {
9+
data case t _ :> {
10+
bool: case bool
11+
char: case char
12+
int : case int
13+
text: case text
14+
unit: case unit
15+
16+
alt 'x 'y: t x ~> t y ~> case (alt x y)
17+
~~> 'x 'y: t x ~> t y ~> case (x ~> y)
18+
pair 'x 'y: t x ~> t y ~> case (x, y)
19+
20+
iso 'x 'y: iso x y ~> t y ~> case x
21+
22+
lazy 'x: ({} ~> t x) ~> case x
23+
}
24+
25+
defaults (type t _) (default 'a: t a) = {
26+
bool = default
27+
char = default
28+
int = default
29+
unit = default
30+
text = default
31+
32+
alt _ _ = default
33+
_ ~~> _ = default
34+
pair _ _ = default
35+
36+
iso _ _ = default
37+
38+
lazy _ = default
39+
}
40+
41+
local i = {to = Opt.case {none = inl {}, some = inr}
42+
from = Alt.case {inl {} = none, inr = some}}
43+
opt a = iso i (alt unit a)
44+
45+
local i = {to = List.case {nil = inl {}, x :: xs = inr (x, xs)}
46+
from = Alt.case {inl {} = nil, inr (x, xs) = x::xs}}
47+
list v = rec vs => lazy fun {} => iso i (alt unit (pair v vs))
48+
}
49+
50+
;; Generic toText
51+
52+
ToText = {type t x = x ~> text}
53+
54+
toText = rec (toText 'x: Rep.t x ~> ToText.t x) => Rep.case ToText.t {
55+
bool = Bool.toText
56+
char c = "'" ++ Text.fromChar c ++ "'"
57+
int = Int.toText
58+
text t = "\"" ++ t ++ "\""
59+
unit {} = "{}"
60+
61+
alt aT bT = Alt.case {
62+
inl a = "(inl " ++ toText aT a ++ ")"
63+
inr b = "(inr " ++ toText bT b ++ ")"
64+
}
65+
66+
(_ ~~> _) _ = "<fun>"
67+
68+
pair aT bT (a, b) = "(" ++ toText aT a ++ ", " ++ toText bT b ++ ")"
69+
70+
iso ab bT = ab.to >> toText bT
71+
72+
lazy th = toText (th {})
73+
}
74+
75+
println rep x = print (toText rep x ++ "\n")
76+
77+
do let ...Rep
78+
println int 101
79+
println (pair bool text) (true, "that")
80+
println (opt bool) (some false)
81+
println (iso {to i = i <> 0, from b = if b then 1 else 0} bool) 1
82+
println (list int) (3 :: (1 :: (4 :: nil)))
83+
84+
;; Generic eq
85+
86+
Eq = {type t x = x ~> x ~> bool}
87+
88+
eq = rec (eq 'x: Rep.t x ~> Eq.t x) => Rep.case Eq.t {
89+
bool = Bool.==
90+
char = Char.==
91+
int = Int.==
92+
text = Text.==
93+
unit _ _ = true
94+
95+
alt aT bT l r = l |> Alt.case {
96+
inl l = r |> Alt.case {inl = eq aT l, inr _ = false}
97+
inr l = r |> Alt.case {inl _ = false, inr = eq bT l}
98+
}
99+
100+
(_ ~~> _) _ _ = false
101+
102+
pair aT bT (l1, l2) (r1, r2) = eq aT l1 r1 && eq bT l2 r2
103+
104+
iso ab bT l r = eq bT (ab.to l) (ab.to r)
105+
106+
lazy th l r = eq (th {}) l r
107+
}
108+
109+
do let ...Rep
110+
test t l r = print ("eq " ++ toText t l ++
111+
" " ++ toText t r ++
112+
" = " ++ toText bool (eq t l r) ++ "\n")
113+
test int 101 42
114+
test (pair int bool) (1, true) (1, true)
115+
test (list int) (3 :: (1 :: nil)) (4 :: (1 :: nil))
116+
test (list int) (4 :: (2 :: nil)) (4 :: (2 :: nil))

examples/trie.1ml

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
local import "prelude"
22

33
FunctionalTrie = {
4-
local
5-
type I (type t _ _) = {
6-
type case _ _
7-
unit 'v : opt v ~> case {} v
8-
alt 'v 'k1 'k2 : t k1 v ~> t k2 v ~> case (alt k1 k2) v
9-
pair 'v 'k1 'k2 : t k1 (t k2 v) ~> case (k1, k2) v
10-
}
11-
...rec {type t _ _} => {type t k v = wrap (m: I t) ~> m.case k v}
12-
I = I t
13-
14-
t
15-
case (m: I) (e: t _ _) = e m
16-
unit vO : t _ _ = fun (m: I) => m.unit vO
17-
alt l r : t _ _ = fun (m: I) => m.alt l r
18-
pair lr : t _ _ = fun (m: I) => m.pair lr
4+
data case t _ _ :> {
5+
unit 'v : opt v ~> case {} v
6+
alt 'v 'k1 'k2 : t k1 v ~> t k2 v ~> case (alt k1 k2) v
7+
pair 'v 'k1 'k2 : t k1 (t k2 v) ~> case (k1, k2) v
8+
}
199

2010
lookup = rec (lookup 'k 'v: t k v ~> k ~> opt v) =>
21-
case {
22-
type case k v = k ~> opt v
11+
case (type fun k v => k ~> opt v) {
2312
unit m {} = m
2413
alt ta tb = Alt.case {inl = lookup ta, inr = lookup tb}
2514
pair ta (a, b) = lookup ta a |> Opt.case {none, some tb = lookup tb b}

lexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ rule token = parse
263263
| "_" { HOLE }
264264
| "&&" { LOGICAL_AND }
265265
| "as" { AS }
266+
| "data" { DATA }
266267
| "do" { DO }
267268
| "else" { ELSE }
268269
| "type_error" { TYPE_ERROR }

parser.mly

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ let parse_error s = raise (Source.Error (Source.nowhere_region, s))
3939
%token IMPORT
4040
%token WRAP_OP UNWRAP_OP
4141
%token ROLL_OP UNROLL_OP
42+
%token DATA
4243

4344
%token EOF
4445

@@ -424,6 +425,8 @@ annexp :
424425
{ $2($1, $3)@@at() }
425426
;
426427
exp :
428+
| DATA name name typparamlist annexp_op typ
429+
{ dataE($2, $3, $4, $5, $6, at())@@at() }
427430
| LET bind IN exp
428431
{ letE($2, $4)@@at() }
429432
| IF exp THEN exp ELSE exp
@@ -504,6 +507,8 @@ atbind :
504507
{ inclB(letE($2, $4)@@at())@@at() }
505508
| IMPORT TEXT
506509
{ InclB(ImportE($2@@ati 2)@@at())@@at() }
510+
| DATA name name typparamlist annexp_op typ
511+
{ InclB(dataE($2, $3, $4, $5, $6, at())@@at())@@at() }
507512
/*
508513
| LPAR bind RPAR
509514
{ $2 }

prelude/index.1mls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ Text: {
8383
print: t ~> {}
8484
}
8585

86+
Unit: {
87+
type t = {}
88+
}
89+
8690
Zero: {
8791
type t
8892
}
@@ -94,6 +98,7 @@ type int = Int.t
9498
type list a = List.t a
9599
type opt a = Opt.t a
96100
type text = Text.t
101+
type unit = Unit.t
97102
type zero = Zero.t
98103

99104
% * + - / : int -> int -> int

0 commit comments

Comments
 (0)