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