Skip to content

Commit dc8bebb

Browse files
committed
Change and generalize syntax of annotations, (un)wraps, (un)rolls
exp : t ;; annot exp :> t ;; seal exp :@ t ;; wrap exp :# t ;; roll exp @: t ;; unroll exp #: t ;; unwrap bind : t = exp := bind = exp : t bind :> t = exp := bind = exp :> t bind :@ t = exp := bind = exp :@ t bind :# t = exp := bind = exp :# t bind @: t = exp := bind = exp @: t bind #: t = exp := bind = exp #: t pat : t ;; annot pat pat :@ t ;; roll pat -> binding unrolled pat :# t ;; wrap pat -> binding unwrapped
1 parent b569fd7 commit dc8bebb

11 files changed

Lines changed: 239 additions & 135 deletions

File tree

README.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ E ::=
115115
fun '(X : T) => E (implicit function/functor/constructor)
116116
E E (application)
117117
if E then E else E : T (conditional)
118-
wrap E : T (impredicative wrapping)
119-
unwrap E : T (unwrapping)
118+
E :# T (impredicative wrapping)
119+
E #: T (unwrapping)
120120
rec (X : T) => E (recursion)
121-
@T E (recursive type roll)
122-
E.@T (recursive type unroll)
121+
E :@ T (recursive type roll)
122+
E @: T (recursive type unroll)
123123
import "path" (static import of module from file at path)
124124
125125
(bindings)
@@ -192,7 +192,7 @@ E ::= ...
192192
E1 || E2 ~> if E1 then true else E2
193193
E1 && E2 ~> if E1 then E2 else false
194194
E : T ~> (fun (X : T) => X) E
195-
E :> T ~> unwrap (wrap E : T) : T
195+
E :> T ~> E :# T #: T
196196
let B in E ~> {B , X = E}.X
197197
rec P => E ~> rec (X : TP) => let P = X in E [2]
198198
E1 ; E2 ~> let _ = E1 in E2
@@ -209,8 +209,8 @@ P ::=
209209
(P1, ..., Pn) ~> {_1 = P1, ..., _n = Pn}
210210
(type X A1 ... An) ~> (X : A1 -> ... -> An -> type)
211211
(type (A1 SYM A2) A3 ... An) ~> (type (SYM) A1 ... An)
212-
wrap P : T ~> ...let $ = unwrap $ : T in {P = $}
213-
@T P ~> ...let $ = $.@T in {P = $}
212+
P :# T ~> ...let $ = $ #: T in {P = $}
213+
P :@ T ~> ...let $ = $ @: T in {P = $}
214214
P : T ~> P = $ : T
215215
P1 as P2 ~> P1, P2
216216
@@ -344,11 +344,11 @@ There are no datatype definitions, recursive types have to be defined
344344
explicitly, and require explicit injection/projection.
345345

346346
```1ml
347-
type stream = rec t => {hd : int, tl : () ~> opt t} ;; creates rec type
348-
single x = @stream{hd = x, tl = fun () => none} ;; @(t) e rolls value into t
349-
@stream{hd = n} = single 5 ;; @(t) p pattern matches on rec value
347+
type stream = rec t => {hd : int, tl : () ~> opt t} ;; creates rec type
348+
single x :@ stream = {hd = x, tl = fun () => none} ;; b :@ t rolls value into t
349+
({hd = n} :@ stream) = single 5 ;; p :@ t pattern matches on rec value
350350
do Int.print n ;; or:
351-
do Int.print (single 7).@stream.hd ;; e.@(t) unrolls rec value directly
351+
do Int.print (single 7 @: stream).hd ;; e @: t unrolls rec value directly
352352
```
353353

354354
#### Recursive Functions
@@ -360,15 +360,15 @@ count = rec self => fun i =>
360360
if i == 0 then () else self (i - 1)
361361
362362
repeat = rec self => fun x =>
363-
@stream{hd = x, tl = fun () => some (self x)}
363+
{hd = x, tl = fun () => some (self x)} :@ stream
364364
```
365365

366366
Mutual recursion is also expressible:
367367

368368
```1ml
369369
{even, odd} = rec (self : {even : int ~> stream, odd : int ~> stream}) => {
370-
even x = @stream{hd = x, tl = fun () => some (self.odd (x + 1))}
371-
odd x = @stream{hd = x, tl = fun () => some (self.even (x + 1))}
370+
even x :@ stream = {hd = x, tl = fun () => some (self.odd (x + 1))}
371+
odd x :@ stream = {hd = x, tl = fun () => some (self.even (x + 1))}
372372
}
373373
```
374374

@@ -392,14 +392,13 @@ Opt :> OPT = {
392392
;; Church encoding; it requires the abstract type opt a to be implemented
393393
;; with a polymorphic (i.e., large) type. Thus, wrap the type.
394394
type opt a = wrap (b : type) -> b -> (a ~> b) ~> b
395-
none = wrap (fun (b : type) (n : b) (s : _ ~> b) => n) : opt _
396-
some x = wrap (fun (b : type) (n : b) (s : _ ~> b) => s x) : opt _
397-
caseopt xo = (unwrap xo : opt _) _
395+
none :# opt _ = fun (b : type) (n : b) (s : _ ~> b) => n
396+
some x :# opt _ = fun (b : type) (n : b) (s : _ ~> b) => s x
397+
caseopt (xo :# opt _) = xo _
398398
}
399399
```
400400

401-
Note how values of type `wrap T` have to be wrapped and unwrapped explicitly,
402-
with a type annotation.
401+
Note how values of type `wrap T` have to be wrapped and unwrapped explicitly.
403402

404403
---
405404

lexer.mll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,14 @@ rule token = parse
253253
| "rec" { REC }
254254
| "then" { THEN }
255255
| "type" { TYPE }
256-
| "unwrap" { UNWRAP }
257256
| "with" { WITH }
258-
| "@" { AT }
259257
| "=" { EQUAL }
260258
| ":" { COLON }
261259
| ":>" { SEAL }
260+
| ":@" { ROLL_OP }
261+
| "@:" { UNROLL_OP }
262+
| ":#" { WRAP_OP }
263+
| "#:" { UNWRAP_OP }
262264
| "->" { ARROW }
263265
| "~>" { SARROW }
264266
| "=>" { DARROW }

paper.1ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ f (id : (a : type) -> a ~> a) = {x = id int 5, y = id bool true}
8787

8888
type SHAPE = {type t, area : t ~> int, v : t}
8989
volume (height : int) (s : SHAPE) = height * s.area s.v
90-
area ss = List.foldl ss 0 (fun a (wrap s : wrap SHAPE) => a + s.area s.v)
90+
area ss = List.foldl ss 0 (fun a (s :# wrap SHAPE) => a + s.area s.v)
9191

9292
type COLL c = {
9393
type key
@@ -266,7 +266,7 @@ type OPT = {
266266
}
267267
Opt :> OPT = {
268268
type opt a = wrap (b : type) -> b -> (a ~> b) ~> b
269-
none 'a = wrap (fun (b : type) (n : b) (s : a ~> b) => n) : opt a
270-
some 'a x = wrap (fun (b : type) (n : b) (s : a ~> b) => s x) : opt a
271-
caseopt 'a 'b xo = (unwrap xo : opt a) b
269+
none 'a :# opt a = fun (b : type) (n : b) (s : a ~> b) => n
270+
some 'a x :# opt a = fun (b : type) (n : b) (s : a ~> b) => s x
271+
caseopt 'a 'b (xo :# opt a) = xo b
272272
}

parser.mly

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,19 @@ let parse_error s = raise (Source.Error (Source.nowhere_region, s))
2626
%}
2727

2828
%token HOLE PRIMITIVE
29-
%token FUN REC LET IN DO WRAP UNWRAP TYPE ELLIPSIS
29+
%token FUN REC LET IN DO WRAP TYPE ELLIPSIS
3030
%token IF THEN ELSE LOGICAL_OR LOGICAL_AND AS
3131
%token EQUAL COLON SEAL ARROW SARROW DARROW
3232
%token WITH
3333
%token LPAR RPAR
3434
%token LBRACE RBRACE
35-
%token DOT AT TICK
35+
%token DOT TICK
3636
%token COMMA SEMI
3737
%token TYPE_ERROR
3838
%token LOCAL
3939
%token IMPORT
40+
%token WRAP_OP UNWRAP_OP
41+
%token ROLL_OP UNROLL_OP
4042

4143
%token EOF
4244

@@ -262,10 +264,6 @@ dotpathexp :
262264
{ $1 }
263265
| dotpathexp DOT label
264266
{ DotE($1, $3)@@at() }
265-
| dotpathexp DOT AT attyp
266-
{ unrollE($1, $4)@@at() }
267-
| dotpathexp DOT AT name
268-
{ unrollE($1, PathT(VarE($4)@@ati 4)@@ati 4)@@at() }
269267
;
270268
atpathexp :
271269
| name
@@ -280,10 +278,6 @@ apppathexp :
280278
{ appE($1, $2)@@at() }
281279
| apppathexp attyp
282280
{ appE($1, TypE($2)@@ati 2)@@at() }
283-
| AT attyp atexp
284-
{ rollE($3, $2)@@at() }
285-
| AT name atexp
286-
{ rollE($3, PathT(VarE($2)@@ati 2)@@ati 2)@@at() }
287281
;
288282
infpathexp :
289283
| apppathexp
@@ -303,10 +297,6 @@ dotexp :
303297
{ $1 }
304298
| dotexp DOT label
305299
{ DotE($1, $3)@@at() }
306-
| dotexp DOT AT attyp
307-
{ unrollE($1, $4)@@at() }
308-
| dotexp DOT AT name
309-
{ unrollE($1, PathT(VarE($4)@@ati 4)@@ati 4)@@at() }
310300
;
311301
atexp :
312302
| name
@@ -339,10 +329,6 @@ appexp :
339329
{ $1 }
340330
| appexp dotexp
341331
{ appE($1, $2)@@at() }
342-
| AT attyp atexp
343-
{ rollE($3, $2)@@at() }
344-
| AT name atexp
345-
{ rollE($3, PathT(VarE($2)@@ati 2)@@ati 2)@@at() }
346332
;
347333
infexp :
348334
| appexp
@@ -356,17 +342,27 @@ infexp :
356342
| infexp LOGICAL_AND appexp
357343
{ andE($1, $3)@@at() }
358344
;
345+
annexp_op :
346+
| COLON
347+
{ annotE }
348+
| SEAL
349+
{ sealE }
350+
| ROLL_OP
351+
{ rollE }
352+
| UNROLL_OP
353+
{ unrollE }
354+
| WRAP_OP
355+
{ wrapE }
356+
| UNWRAP_OP
357+
{ unwrapE }
358+
;
359359
annexp :
360-
| infexp optannot
361-
{ opt annotE($1, $2)@@at() }
360+
| infexp
361+
{ $1 }
362362
| TYPE typ
363363
{ TypE($2)@@at() }
364-
| annexp SEAL typ
365-
{ sealE($1, $3)@@at() }
366-
| WRAP infexp COLON typ
367-
{ wrapE($2, $4)@@at() }
368-
| UNWRAP infexp COLON typ
369-
{ unwrapE($2, $4)@@at() }
364+
| annexp annexp_op typ
365+
{ $2($1, $3)@@at() }
370366
;
371367
inexp :
372368
| annexp
@@ -403,18 +399,42 @@ funbind :
403399
{ ($3, $2 @ $4 @ $6) }
404400
;
405401

402+
bindann_op :
403+
| COLON
404+
{ annotE }
405+
| SEAL
406+
{ sealE }
407+
| ROLL_OP
408+
{ rollE }
409+
| UNROLL_OP
410+
{ unrollE }
411+
| WRAP_OP
412+
{ wrapE }
413+
| UNWRAP_OP
414+
{ unwrapE }
415+
;
416+
bindann :
417+
| bindann_op typ
418+
{ fun e -> $1(e, $2)@@span[ati 2; e.at] }
419+
;
420+
bindanns :
421+
| bindann
422+
{ $1 }
423+
| bindanns bindann
424+
{ fun e -> $2 ($1 e) }
425+
;
426+
bindanns_opt :
427+
|
428+
{ fun e -> e }
429+
| bindanns
430+
{ $1 }
431+
;
432+
406433
atbind :
407-
| funbind optannot EQUAL exp
408-
{ let (head, params) = $1 in
409-
VarB(head, funE(params,
410-
opt annotE($4, $2)@@span[ati 2; ati 4])@@at())@@at() }
411-
| funbind SEAL typ EQUAL exp
412-
{ let (head, params) = $1 in
413-
VarB(head, funE(params, sealE($5, $3)@@span[ati 3; ati 5])@@at())@@at() }
414-
| head SEAL typ EQUAL exp
415-
{ VarB($1, sealE($5, $3)@@span[ati 3; ati 5])@@at() }
416-
| pat EQUAL exp
417-
{ patB($1, $3)@@at() }
434+
| funbind bindanns_opt EQUAL exp
435+
{ let (head, params) = $1 in VarB(head, funE(params, $2($4))@@at())@@at() }
436+
| atpat bindanns_opt EQUAL exp
437+
{ patB($1, $2($4))@@at() }
418438
| name
419439
{ VarB($1, VarE($1.it@@at())@@at())@@at() }
420440
| typpat EQUAL typ
@@ -461,19 +481,19 @@ atpat :
461481
annotP(headP(head)@@head.at,
462482
funT(typparams, TypT@@at(), Pure@@at())@@at())@@at() }
463483
;
464-
apppat :
465-
| atpat
466-
{ $1 }
467-
| AT attyp atpat
468-
{ rollP($3, $2)@@at() }
469-
| AT name atpat
470-
{ rollP($3, PathT(VarE($2)@@ati 2)@@ati 2)@@at() }
484+
annpat_op :
485+
| COLON
486+
{ annotP }
487+
| ROLL_OP
488+
{ rollP }
489+
| WRAP_OP
490+
{ wrapP }
471491
;
472492
annpat :
473-
| apppat optannot
474-
{ opt annotP($1, $2)@@at() }
475-
| WRAP apppat COLON typ
476-
{ wrapP($2, $4)@@at() }
493+
| atpat
494+
{ $1 }
495+
| annpat annpat_op typ
496+
{ $2($1, $3)@@at() }
477497
;
478498
pat :
479499
| annpat

prelude.1ml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ type OPT = {
112112
}
113113
Opt :> OPT = {
114114
type opt a = wrap (b : type) -> (() ~> b) -> (a ~> b) ~> b
115-
none 'a = wrap (fun (b : type) (n : () ~> b) (s : a ~> b) => n ()) : opt a
116-
some 'a x = wrap (fun (b : type) (n : () ~> b) (s : a ~> b) => s x) : opt a
117-
caseopt xo = (unwrap xo : opt _) _
115+
none 'a :# opt a = fun (b : type) (n : () ~> b) (s : a ~> b) => n ()
116+
some 'a x :# opt a = fun (b : type) (n : () ~> b) (s : a ~> b) => s x
117+
caseopt (xo :# opt _) = xo _
118118
}
119119
...Opt
120120

@@ -129,11 +129,11 @@ type ALT = {
129129
}
130130
Alt :> ALT = {
131131
type alt a b = wrap (c : type) -> (a ~> c) -> (b ~> c) ~> c
132-
left 'a 'b x =
133-
wrap (fun (c : type) (l : a ~> c) (r : b ~> c) => l x) : alt a b
134-
right 'a 'b x =
135-
wrap (fun (c : type) (l : a ~> c) (r : b ~> c) => r x) : alt a b
136-
casealt xy = (unwrap xy : alt _ _) _
132+
left 'a 'b x :# alt a b =
133+
fun (c : type) (l : a ~> c) (r : b ~> c) => l x
134+
right 'a 'b x :# alt a b =
135+
fun (c : type) (l : a ~> c) (r : b ~> c) => r x
136+
casealt (xy :# alt _ _) = xy _
137137
}
138138
...Alt
139139

@@ -163,11 +163,11 @@ type LIST = {
163163
List :> LIST = {
164164
...{
165165
type list a = wrap (b : type) -> b -> (a ~> b ~> b) ~> b
166-
nil 'a = wrap (fun (b : type) (n : b) (c : a ~> b ~> b) => n) : list _
167-
cons x xs =
168-
wrap (fun (b : type) (n : b) (c : _ ~> b ~> b) =>
169-
c x ((unwrap xs : list _) b n c)) : list _
170-
foldr xs = (unwrap xs : list _) _
166+
nil 'a :# list _ = fun (b : type) (n : b) (c : a ~> b ~> b) => n
167+
cons x (xs :# list _) :# list _ =
168+
fun (b : type) (n : b) (c : _ ~> b ~> b) =>
169+
c x (xs b n c)
170+
foldr (xs :# list _) = xs _
171171
} :> LIST_CORE
172172
isNil xs = foldr xs true (fun _ _ => false)
173173
head xs = foldr xs none (fun x _ => some x)

prelude/index.1ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ Alt :> {
3333
case 'a 'b 'o: {inl: a ~> o, inr: b ~> o} -> t a b ~> o
3434
} = {
3535
type t a b = wrap 'o -> {inl: a ~> o, inr: b ~> o} ~> o
36-
inl x = wrap (fun c => c.inl x): t _ _
37-
inr x = wrap (fun c => c.inr x): t _ _
38-
case c (wrap x: t _ _) = x c
36+
inl x :# t _ _ = fun c => c.inl x
37+
inr x :# t _ _ = fun c => c.inr x
38+
case c (x :# t _ _) = x c
3939
}
4040

4141
Alt = {
@@ -69,9 +69,9 @@ Pair = {
6969
List = {
7070
local ...Opt, ...Fun
7171
...rec {type t _} => {type t x = Opt.t (x, t x)}
72-
nil = @(t _) none
73-
hd :: tl = @(t _) (some (hd, tl))
74-
case {nil, (::)} (@(t _) x) = x |> Opt.case {
72+
nil :@ t _ = none
73+
hd :: tl :@ t _ = some (hd, tl)
74+
case {nil, (::)} (x :@ t _) = x |> Opt.case {
7575
none = nil
7676
some (hd, tl) = hd :: tl
7777
}

0 commit comments

Comments
 (0)