Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 2017 Jason Carr |
2 | * Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh | |
3 | * Jagannathan, and Stephen Weeks. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | structure Stream: STREAM = | |
10 | struct | |
11 | ||
12 | datatype 'a t = T of ('a * 'a t) option Promise.t | |
13 | ||
14 | fun delayTh th = T (Promise.delay th) | |
15 | fun force (T p) = Promise.force p | |
16 | ||
17 | fun 'a delay (th: unit -> 'a t): 'a t = delayTh (force o th) | |
18 | ||
19 | fun empty () = delayTh (fn () => NONE) | |
20 | ||
21 | fun cons (x, s) = delayTh (fn () => SOME (x, s)) | |
22 | ||
23 | fun single x = cons (x, empty ()) | |
24 | ||
25 | fun 'a append (s: 'a t, s': 'a t): 'a t = | |
26 | let | |
27 | fun loop (s) = | |
28 | delay (fn () => | |
29 | case force s of | |
30 | NONE => s' | |
31 | | SOME (x, s') => cons (x, loop s')) | |
32 | in loop s | |
33 | end | |
34 | ||
35 | fun map (s, f) = | |
36 | let | |
37 | fun loop s = | |
38 | delay (fn () => | |
39 | case force s of | |
40 | NONE => empty () | |
41 | | SOME (x, s) => cons (f x, loop s)) | |
42 | in loop s | |
43 | end | |
44 | ||
45 | fun appendMap (s, f) = | |
46 | let | |
47 | fun loop (s) = | |
48 | delay (fn () => | |
49 | case force s of | |
50 | NONE => empty () | |
51 | | SOME (x, s) => append (f x, loop s)) | |
52 | in loop s | |
53 | end | |
54 | ||
55 | fun toList (s) = | |
56 | case force s of | |
57 | NONE => [] | |
58 | | SOME (x, s) => x :: toList s | |
59 | ||
60 | fun fromList l = | |
61 | case l of | |
62 | [] => empty () | |
63 | | x::xs => | |
64 | cons (x, delay (fn () => fromList xs)) | |
65 | ||
66 | fun last (s) = | |
67 | let | |
68 | fun loop (z, s) = | |
69 | case force s of | |
70 | NONE => z | |
71 | | SOME (x, s) => loop (SOME x, s) | |
72 | in loop (NONE, s) | |
73 | end | |
74 | ||
75 | fun isEmpty (s) = | |
76 | case force (s) of | |
77 | NONE => true | |
78 | | SOME _ => false | |
79 | ||
80 | fun layout f s = List.layout f (toList s) | |
81 | ||
82 | fun keep (s, p) = | |
83 | let | |
84 | fun loop s = | |
85 | delay | |
86 | (fn () => | |
87 | case force s of | |
88 | NONE => empty () | |
89 | | SOME (x, s) => if p x | |
90 | then cons (x, loop s) | |
91 | else loop s) | |
92 | in loop s | |
93 | end | |
94 | ||
95 | fun firstN (s, n: int) = | |
96 | let | |
97 | fun loop (n, s, ac) = | |
98 | if n <= 0 | |
99 | then rev ac | |
100 | else (case force s of | |
101 | NONE => Error.bug "Stream.firstN" | |
102 | | SOME (x, s) => loop (n - 1, s, x :: ac)) | |
103 | in loop (n, s, []) | |
104 | end | |
105 | ||
106 | fun firstNSafe (s, n: int) = | |
107 | let | |
108 | fun loop (n, s, ac) = | |
109 | if n <= 0 | |
110 | then rev ac | |
111 | else (case force s of | |
112 | NONE => rev ac | |
113 | | SOME (x, s) => loop (n - 1, s, x :: ac)) | |
114 | in loop (n, s, []) | |
115 | end | |
116 | ||
117 | fun nth (s, n: int) = | |
118 | case force s of | |
119 | NONE => Error.bug "nth" | |
120 | | SOME (x, s) => if n <= 0 then x else nth (s, n - 1) | |
121 | ||
122 | fun 'a infinite (start: 'a, next: 'a -> 'a): 'a t = | |
123 | let fun loop (a: 'a) = delay (fn () => cons (a, loop (next a))) | |
124 | in loop start | |
125 | end | |
126 | ||
127 | end |