1
2
3
4
5 data list a =
6 | Nil
7 | Cons { head: a; tail: list a }
8
9
10
11
12
13
14
15 mutable data cell a =
16 | Cell { head: a; tail: () }
17
18
19
20
21
22
23
24
25
26
27
28
29
30 val freeze [a] (consumes c: cell a, xs: unknown) : (| c @ Cons { head: a; tail = xs }) =
31 c.tail <- xs;
32 tag of c <- Cons
33
34
35
36
37
38
39
40
41
42
43
44
45 val nil =
46 Nil
47
48 val cons [a] (consumes x: a, consumes xs: list a) : list a =
49 Cons { head = x; tail = xs }
50
51 val two [a] (consumes x1: a, consumes x2: a) : list a =
52 Cons { head = x1; tail = Cons { head = x2; tail = Nil }}
53
54 val three [a] (consumes x1: a, consumes x2: a, consumes x3: a) : list a =
55 Cons { head = x1; tail = Cons { head = x2; tail = Cons { head = x3; tail = Nil }}}
56
57 val init [a, p : perm] (n : int, f : (int | p) -> a | p) : list a =
58 let rec loop (i : int | p) : list a =
59 if i = n then
60 Nil
61 else
62 Cons { head = f i; tail = loop (i + 1) }
63 in
64 loop 0
65
66
67
68
69
70
71
72
73 val rec length_aux [a] (accu: int, xs: list a) : int =
74 if xs then length_aux (accu + 1, xs.tail) else accu
75
76 val length [a] (xs: list a) : int =
77 length_aux (0, xs)
78
79
80
81
82
83
84
85
86 val hd [a] (consumes xs: Cons { head: a; tail: unknown }) : a =
87 xs.head
88
89 val tl [a] (consumes xs: Cons { head: unknown; tail: list a }) : list a =
90 xs.tail
91
92
93
94
95
96 val rec nth_aux [a] (consumes xs: list a, n: int) : a =
97 if xs then
98 if n = 0 then xs.head else nth_aux (xs.tail, n - 1)
99 else
100 fail
101
102 val nth [a] (consumes xs: list a, n: int) : a =
103 if n < 0 then fail else nth_aux (xs, n)
104
105 val rec chop [a] (k: int, consumes xs: list a) : list a =
106 if k = 0 then xs
107 else if xs then chop (k - 1, xs.tail)
108 else fail
109
110
111
112
113 val rec splitAt [a] (k: int, consumes xs: list a) : (list a, list a) =
114 if k = 0 then
115 Nil, xs
116 else if xs then begin
117 let prefix, suffix = splitAt (k - 1, xs.tail) in
118 Cons { head = xs.head; tail = prefix }, suffix
119 end
120 else fail
121
122
123
124 val rec splitAtAux [a] (k: int, consumes xs: list a, consumes c: cell a) : (list a | c @ list a) =
125 if k = 0 then begin
126 freeze (c, Nil);
127 xs
128 end
129 else if xs then begin
130 let d = Cell { head = xs.head; tail = () } in
131 freeze (c, d);
132 splitAtAux (k - 1, xs.tail, d)
133 end
134 else fail
135
136 val splitAt [a] (k: int, consumes xs: list a) : (list a, list a) =
137 if k = 0 then
138 Nil, xs
139 else if xs then begin
140 let ys = Cell { head = xs.head; tail = () } in
141 let zs = splitAtAux (k - 1, xs.tail, ys) in
142 ys, zs
143 end
144 else fail
145
146
147
148
149
150
151
152
153
154 val rec append [a] (consumes xs: list a, consumes ys: list a) : list a =
155 if xs then
156 Cons { head = xs.head; tail = append (xs.tail, ys) }
157 else
158 ys
159
160
161
162 val rec rev_append [a] (consumes xs: list a, consumes ys: list a) : list a =
163 if xs then
164 rev_append (xs.tail, Cons { head = xs.head; tail = ys })
165 else
166 ys
167
168 val rev [a] (consumes xs: list a) : list a =
169 rev_append (xs, Nil)
170
171 val append [a] (consumes xs: list a, consumes ys: list a) : list a =
172 rev_append (rev xs, ys)
173
174
175
176
177 val rec appendAux [a] (
178 consumes dst: cell a,
179 consumes xs: list a,
180 consumes ys: list a)
181 : (| dst @ list a)
182 =
183 if xs then begin
184 let dst' = Cell { head = xs.head; tail = () } in
185 freeze (dst, dst');
186 appendAux (dst', xs.tail, ys)
187 end
188 else
189 freeze (dst, ys)
190
191 val append [a] (consumes xs: list a, consumes ys: list a) : list a =
192 if xs then begin
193 let dst = Cell { head = xs.head; tail = () } in
194 appendAux (dst, xs.tail, ys);
195 dst
196 end
197 else
198 ys
199
200
201
202
203
204 val rec flatten [a] (consumes xss : list (list a)) : list a =
205 if xss then
206 append (xss.head, flatten xss.tail)
207 else
208 Nil
209
210
211
212
213
214
215
216
217
218 val rec map [a1, a2, b, p : perm] (
219 consumes xs: list a1,
220 f: (consumes x: a1 | p) -> ( b | x @ a2)
221 | p) : (list b | xs @ list a2)
222 =
223 if xs then
224 Cons { head = f xs.head; tail = map (xs.tail, f) }
225 else
226 Nil
227
228 val rev_map [a1, a2, b, p : perm] (
229 consumes xs: list a1,
230 f: (consumes x: a1 | p) -> ( b | x @ a2)
231 | p) : (list b | xs @ list a2)
232 =
233 let rec rev_map_aux (consumes accu: list b, consumes xs: list a1 | p) : (list b | xs @ list a2) =
234 if xs then
235 rev_map_aux (Cons { head = f xs.head; tail = accu }, xs.tail)
236 else
237 accu
238 in
239 rev_map_aux (Nil, xs)
240
241
242
243
244
245
246
247
248
249 val rec iter [a1, a2, p : perm] (
250 consumes xs: list a1,
251 f: (consumes x: a1 | p)
252 -> (| x @ a2)
253 | p
254 ) : (| xs @ list a2)
255 =
256 if xs then begin
257 f xs.head;
258 iter (xs.tail, f)
259 end
260
261
262
263
264 val simpler_iter [a] (xs: list a, f: a -> ()) : () =
265 iter (xs, f)
266
267
268
269
270
271
272
273
274
275
276
277
278 val rec fold_left [a1, a2, b] (
279 f: (consumes b, consumes x: a1) -> (b | x @ a2),
280 consumes accu: b, consumes xs: list a1) : (b | xs @ list a2)
281 =
282 if xs then
283 fold_left (f, f (accu, xs.head), xs.tail)
284 else
285 accu
286
287 val rec fold_right [a1, a2, b] (
288 f: (consumes x: a1, consumes b) -> (b | x @ a2),
289 consumes xs: list a1, consumes accu: b) : (b | xs @ list a2)
290 =
291 if xs then
292 f (xs.head, fold_right (f, xs.tail, accu))
293 else
294 accu
295
296
297
298
299
300
301
302
303 val rec for_all [a, p : perm] (ok: (a | p) -> bool, xs: list a | p) : bool =
304 if xs then
305 if ok xs.head then for_all (ok, xs.tail) else False
306 else
307 True
308
309 val rec rich_for_all
310 [a, p : perm, q : perm] (ok: (a | p) -> rich_bool q empty, xs: list a | p) : rich_bool q empty =
311 match xs with
312 | Nil ->
313 RichTrue
314 | Cons { head; tail } ->
315 conjunction (
316 ok head,
317 fun (| p * tail @ list a) : rich_bool q empty =
318 rich_for_all (ok, tail)
319 )
320 end
321
322 val rec rich_for_all_with_inlined_conjunction
323 [a, p : perm, q : perm] (ok: (a | p) -> rich_bool q empty, xs: list a | p) : rich_bool q empty =
324 match xs with
325 | Nil ->
326 RichTrue
327 | Cons { head; tail } ->
328 ok head && rich_for_all_with_inlined_conjunction (ok, tail)
329 end
330
331 val rec exists [a, p : perm] (ok: (a | p) -> bool, xs: list a | p) : bool =
332 if xs then
333 if ok xs.head then True else exists (ok, xs.tail)
334 else
335 False
336
337 val rec rich_exists_with_inlined_disjunction
338 [a, p : perm, q : perm] (ok: (a | p) -> rich_bool empty q, xs: list a | p) : rich_bool empty q =
339 match xs with
340 | Nil ->
341 RichFalse
342 | Cons { head; tail } ->
343 ok head || rich_exists_with_inlined_disjunction (ok, tail)
344 end
345
346
347
348
349
350
351
352 val rec find [a, p : perm] (ok: (a | p) -> bool, consumes xs: list a | p) : list a =
353 if xs then
354 if ok xs.head then xs else find (ok, xs.tail)
355 else
356 xs
357
358
359
360
361 val rec remove [a, p : perm] (ok : (a | p) -> bool, consumes xs: list a | p) : list a =
362 if xs then
363 if ok xs.head then xs.tail else Cons { head = xs.head; tail = remove (ok, xs.tail) }
364 else
365 xs
366
367
368
369
370
371 val mem [a, p : perm] (equal: (a, a | p) -> bool, x: a, consumes xs: list a | p) : list a =
372 let ok (y : a | x @ a * p) : bool =
373 equal (x, y)
374 in
375 find (ok, xs)
376
377 val rec mem [a, p : perm] (equal: (a, a | p) -> bool, x: a, consumes xs: list a | p) : list a =
378 if xs then
379 if equal (x, xs.head) then xs else mem (equal, x, xs.tail)
380 else
381 Nil
382
383
384
385
386 val assoc [a, b, p : perm] (equal: (a, a | p) -> bool, x: a, consumes xs: list (a, b) | p) : list (a, b) =
387 let ok (y: a, _: b | x @ a * p) : bool =
388 equal (x, y)
389 in
390 find [(a, b), (x @ a * p)] (ok, xs)
391
392
393
394
395
396
397
398
399
400
401 val filter [a, p : perm] (consumes xs: list a, ok: (a | p) -> bool | p) : list a =
402 let f (consumes accu: list a, consumes x: a | p) : list a =
403 if ok x then Cons { head = x; tail = accu } else accu
404 in
405 rev (fold_left [a, unknown, (list a | p)] (f, Nil, xs))
406
407 val partition [a] (p: a -> bool, consumes xs: list a) : (list a, list a) =
408 let f (consumes (yes: list a, no: list a), consumes x: a) : (list a, list a) =
409 if p x then
410 Cons { head = x; tail = yes }, no
411 else
412 yes, Cons { head = x; tail = no }
413 in
414 let (yes, no) = fold_left [a, unknown, (list a, list a)] (f, (Nil, Nil), xs) in
415 rev yes, rev no
416
417
418
419
420
421 val rec split [a, b] (consumes xys : list (a, b)) : (list a, list b) =
422 if xys then begin
423 let x, y = xys.head in
424 let xs, ys = split xys.tail in
425 Cons { head = x; tail = xs },
426 Cons { head = y; tail = ys }
427 end
428 else
429 Nil,
430 Nil
431
432 val rec combine [a, b] (consumes xs: list a, consumes ys: list b) : list (a, b) =
433 match xs, ys with
434 | Cons, Cons ->
435 Cons { head = (xs.head, ys.head); tail = combine (xs.tail, ys.tail) }
436 | Nil, Nil ->
437 Nil
438 | Nil, Cons ->
439 Nil
440 | Cons, Nil ->
441 Nil
442 end
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 val splitAtOrShareAndChop [a] (
465 dupa: reflection::duplicability a,
466 k: int,
467 consumes xs: list a
468 ) : (list a, list a) =
469 if dupa then
470
471
472
473 xs, chop (k, xs)
474 else
475
476
477
478
479
480 splitAt (k, xs)
481
482
483
484
485
486
487
488
489 val rec merge [a] (
490 cmp: (a, a) -> int,
491 consumes xs: list a,
492 consumes ys: list a
493 ) : list a =
494 match xs, ys with
495 | Nil, _ ->
496 ys
497 | _, Nil ->
498 xs
499 | Cons { head = x }, Cons { head = y } ->
500 if cmp (x, y) <= 0
501 then Cons { head = x; tail = merge (cmp, xs.tail, ys) }
502 else Cons { head = y; tail = merge (cmp, xs, ys.tail) }
503 end
504
505 val sort [a] (
506 dupa: reflection::duplicability a,
507 cmp: (a, a) -> int,
508 consumes xs: list a
509 ) : list a =
510
511
512
513 let cmp (sense: int, x: a, y: a) : int =
514 sense * cmp (x, y)
515 in
516
517
518
519 let rec rev_merge (sense: int, consumes xs: list a, consumes ys: list a, consumes accu: list a) : list a =
520 if xs then
521 if ys then begin
522 let x = xs.head
523 and y = ys.head in
524 if cmp (sense, x, y) <= 0
525 then rev_merge (sense, xs.tail, ys, Cons { head = x; tail = accu })
526 else rev_merge (sense, xs, ys.tail, Cons { head = y; tail = accu })
527 end
528 else
529 rev_append (xs, accu)
530 else
531 rev_append (ys, accu)
532 in
533
534
535
536 let rec sort (sense: int, n: int, consumes xs: list a) : list a =
537
538 if n = 2 then
539 match xs with
540 | Cons { head = x1; tail = Cons { head = x2; tail = any }} ->
541 if cmp (sense, x1, x2) <= 0 then two (x1, x2) else two (x2, x1)
542 | _ ->
543 fail
544 end
545 else if n = 3 then
546 match xs with
547 | Cons { head = x1; tail = Cons { head = x2; tail = Cons { head = x3; tail = any }}} ->
548 if cmp (sense, x1, x2) <= 0 then begin
549 if cmp (sense, x2, x3) <= 0 then three (x1, x2, x3)
550 else if cmp (sense, x1, x3) <= 0 then three (x1, x3, x2)
551 else three (x3, x1, x2)
552 end else begin
553 if cmp (sense, x1, x3) <= 0 then three (x2, x1, x3)
554 else if cmp (sense, x2, x3) <= 0 then three (x2, x3, x1)
555 else three (x3, x2, x1)
556 end
557 | _ ->
558 fail
559 end
560
561 else begin
562 let n1 = n / 2 in
563 let n2 = n - n1 in
564 let xs1, xs2 = splitAtOrShareAndChop (dupa, n1, xs) in
565 let xs1 = sort (-sense, n1, xs1) in
566 let xs2 = sort (-sense, n2, xs2) in
567 rev_merge (-sense, xs1, xs2, Nil)
568 end
569 in
570 let n = length xs in
571 if n < 2 then xs else sort (1, n, xs)
572
573
574
575
576
577 val rec equal [a, b] (eq: (a, b) -> bool, xs: list a, ys: list b) : bool =
578 if xs then
579 if ys then
580 if eq (xs.head, ys.head) then
581 equal (eq, xs.tail, ys.tail)
582 else
583 False
584 else
585 False
586 else
587 if ys then
588 False
589 else
590 True
591
592 val rec compare [a, b] (cmp: (a, b) -> int, xs: list a, ys: list b) : int =
593 if xs then
594 if ys then begin
595 let c = cmp (xs.head, ys.head) in
596 if c = 0 then
597 compare (cmp, xs.tail, ys.tail)
598 else
599 c
600 end
601 else
602 1
603 else
604 if ys then
605 -1
606 else
607 0
608
609
610
611
612
613
614
615 val rec segment2list [a] duplicable a => (x: array a, i: int, j: int, consumes accu: list a) : list a =
616 if i < j then
617 segment2list (x, i, j - 1, Cons { head = array::get (x, j - 1); tail = accu })
618 else
619 accu
620
621 val array2list [a] duplicable a => (x: array a) : list a =
622 segment2list (x, 0, array::length x, Nil)
623
624
625
626
627
628
629 val list2array [a] (consumes xs: list a) : array a =
630 let n = length xs in
631 let r = newref xs in
632 array::init (Up, n, fun (i: int | r @ ref (list a)) : a =
633 match !r with
634 | Cons { head; tail } ->
635 r := tail;
636 head
637 | Nil ->
638 fail
639 end
640 )
641
642
643
644
645
646