Import Upstream version 20180207
[hcoop/debian/mlton.git] / lib / mlton / basic / stream.sml
CommitLineData
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
9structure Stream: STREAM =
10struct
11
12datatype 'a t = T of ('a * 'a t) option Promise.t
13
14fun delayTh th = T (Promise.delay th)
15fun force (T p) = Promise.force p
16
17fun 'a delay (th: unit -> 'a t): 'a t = delayTh (force o th)
18
19fun empty () = delayTh (fn () => NONE)
20
21fun cons (x, s) = delayTh (fn () => SOME (x, s))
22
23fun single x = cons (x, empty ())
24
25fun '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
35fun 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
45fun 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
55fun toList (s) =
56 case force s of
57 NONE => []
58 | SOME (x, s) => x :: toList s
59
60fun fromList l =
61 case l of
62 [] => empty ()
63 | x::xs =>
64 cons (x, delay (fn () => fromList xs))
65
66fun 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
75fun isEmpty (s) =
76 case force (s) of
77 NONE => true
78 | SOME _ => false
79
80fun layout f s = List.layout f (toList s)
81
82fun 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
95fun 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
106fun 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
117fun 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
122fun '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
127end