on master help sign in
Add more documentation (mainly adding more examples) and change to the name `splitWith`
commitcc5be70ac429e1b771bbd340694bd78176f5dc9b authorEvan Czaplicki <info@elm-lang.org> dateFri 13 Dec 2013, 16:15 (13 years ago) parent8a9fbbc
1 file changed+171−70
libraries/Lazy/Stream.elm+171−70
libraries/Lazy/Stream.elm+171−70
@@ -3,22 +3,19 @@ module Lazy.Stream ( head, tail
33 , map, apply, zip, zipWith, scanl
44 , take, drop, splitAt
55 , sampleOn
6− , filter, takeWhile, dropWhile, splitWhen
6+ , filter, takeWhile, dropWhile, splitWith
77 ) where
88
9−{-| Library for Infinite Streams
9+{-| This library is for creating and manipulating infinite streams
1010
1111# Create
12−@docs cons, cons', iterate, repeat, cycle
12+@docs cons, cons', repeat, cycle, iterate
1313
14−# Observe
15−@docs head, tail, sampleOn, take, drop, splitAt
14+# Use
15+@docs head, tail, sampleOn, take, takeWhile, drop, dropWhile, splitAt, splitWith
1616
1717# Transform
18−@docs map, apply, zip, zipWith, scanl
19−
20−# Converge
21−@docs filter, takeWhile, dropWhile, splitWhen
18+@docs map, zip, zipWith, scanl, filter, apply
2219
2320-}
2421
@@ -31,88 +28,170 @@ data Stream a = S (Lazy (a, Stream a))
3128unS : Stream a -> (a, Stream a)
3229unS (S t) = force t
3330
34−{-| Compute the first element of a Stream -}
31+{-| Get the first element of a stream, called the `head`.
32+
33+```haskell
34+head ones == 1
35+```
36+-}
3537head : Stream a -> a
3638head = fst . unS
3739
38−{-| Compute the next piece of a Stream -}
40+{-| Drop the `head` of a stream, leaving you with the `tail`.
41+
42+```haskell
43+-- 1, 1, 1, 1, ...
44+stillAllOnes = tail
45+```
46+-}
3947tail : Stream a -> Stream a
4048tail = snd . unS
4149
42−{-| Create a Stream -}
50+{-| Create a stream:
51+
52+```haskell
53+-- 1, 1, 1, 1, ...
54+ones = cons 1 (\() -> ones)
55+```
56+ -}
4357cons : a -> (() -> Stream a) -> Stream a
4458cons x txs = let mtxs = lazy txs in
4559 S . lazy <| \() ->
4660 (x, force mtxs)
4761
48−{-| Lazily create a Stream. -}
62+{-| Create a stream that is slightly more lazy. Notice that the
63+head of the stream is defined within the thunk, so its evaluation
64+is delayed. This is nice when each element of the stream is costly to compute.
65+
66+```haskell
67+-- 1, 1, 1, 1, ...
68+ones = cons' (\_ -> (1,ones))
69+```
70+-}
4971cons' : (() -> (a, Stream a)) -> Stream a
5072cons' = S . lazy
5173
52−{-| Create a stream of repeated applications of f to x:
74+{-| Iteratively apply a function to a value:
5375
54− iterate f x = S.cons x (S.cons (f x) (S.cons (f (f x)) ...))
76+```haskell
77+-- x, f x, f (f x), f (f (f x)), ...
78+iterate f x
79+
80+-- 2, 4, 8, 16, ...
81+powersOf2 = iterate (\n -> n^2) 2
82+```
5583-}
5684iterate : (a -> a) -> a -> Stream a
57−iterate f x = cons' <| \() ->
58− (x, iterate f (f x))
85+iterate f x =
86+ cons' <| \_ -> (x, iterate f (f x))
87+
88+{-| Repeat a value infinitely:
5989
60−{-| Create an infinite Stream of xs. -}
90+```haskell
91+-- 1, 1, 1, 1, ...
92+ones = repeat 1
93+```
94+ -}
6195repeat : a -> Stream a
6296repeat x = let go = cons x <| \() -> go
6397 in go
6498
65−{-| Cycle through the elements of the nonempty list (x :: xs) -}
99+{-| Infinitely cycle through a list, where the head and tail of
100+the list are given separately to ensure that no one tries to cycle
101+on an empty list:
102+
103+```haskell
104+-- "Alice", "Bob", "Alice", "Bob", ...
105+cycle "Alice" ["Bob"]
106+```
107+-}
66108cycle : a -> [a] -> Stream a
67−cycle x xs = let cycle' ys = case ys of
68− [] -> go
69− (y :: ys) -> cons y <| \() ->
70− cycle' ys
71− go = cons' <| \() ->
72− (x, cycle' xs)
73− in go
74−
75−{-| Apply a function to every element of a Stream. -}
109+cycle x xs =
110+ let cycle' ys = case ys of
111+ [] -> go
112+ (y :: ys) -> cons y (\_ -> cycle' ys)
113+ go = cons' <| \_ -> (x, cycle' xs)
114+ in go
115+
116+{-| Apply a function to every element of a Stream.
117+
118+```haskell
119+-- 2, 2, 2, 2, ...
120+twos = map (\n -> n + 1) ones
121+```
122+-}
76123map : (a -> b) -> Stream a -> Stream b
77−map f xs = cons' <| \() ->
78− (f (head xs), map f (tail xs))
124+map f xs =
125+ cons' <| \_ -> (f (head xs), map f (tail xs))
79126
80−{-| Pairwise apply a stream of functions to a stream of inputs.
81− Together with map, generalizes zipWith to n arguments.
127+{-| Pairwise apply a stream of functions to a stream of arguments.
128+When paired with `map`, this can be used to emulate `zipWith` over *n* streams.
82129
83− zipWith2 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
84− zipWith2 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
130+```haskell
131+zipWith3 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
132+zipWith3 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
133+```
85134-}
86135apply : Stream (a -> b) -> Stream a -> Stream b
87136apply fs xs = zipWith (<|) fs xs
88137
89−{-| Combine two streams, combining them into tuples pairwise. -}
90−zip : Stream a -> Stream b -> Stream (a, b)
138+{-| Combine two streams, putting them into tuples pairwise:
139+
140+```haskell
141+-- (1,2), (1,4), (1,8), (1,16), ...
142+pairs = zip ones powersOf2
143+```
144+-}
145+zip : Stream a -> Stream b -> Stream (a,b)
91146zip = zipWith (\x y -> (x,y))
92147
93−{-| Combine two streams, combining them with the given function. -}
148+{-| Combine two streams, applying the given function pairwise:
149+
150+```haskell
151+-- 3, 5, 9, 17, ...
152+zipWith (+) ones powersOf2
153+```
154+-}
94155zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
95156zipWith f xs ys = cons' <| \() ->
96157 (f (head xs) (head ys),
97158 zipWith f (tail xs) (tail ys))
98159
99−{-| Reduce a Stream from the left, building an infinite stream of reductions. -}
160+{-| Scan over a stream from the left, building an infinite stream of reductions.
161+
162+```haskell
163+-- 0, 1, 2, 3, ...
164+runningTotal = scanl (+) 0 ones
165+```
166+-}
100167scanl : (a -> b -> b) -> b -> Stream a -> Stream b
101−scanl f init xs = cons' <| \() ->
102− (init,
103− scanl f (f (head xs) init) (tail xs))
168+scanl f init xs =
169+ cons' <| \() -> (init, scanl f (f (head xs) init) (tail xs))
104170
105−{-| Compute the first n elements of a stream into a list. -}
171+{-| Take the first *n* elements of a stream
172+
173+```haskell
174+take 5 powersOf2 == [2,4,8,16,32]
175+```
176+-}
106177take : Int -> Stream a -> [a]
107178take n xs = fst <| splitAt n xs
108179
109−{-| Drop n elements from the front of a stream. -}
180+{-| Drop the first *n* elements of a stream
181+
182+```haskell
183+-- 64, 128, 256, 512, ...
184+drop 5 powersOf2
185+```
186+-}
110187drop : Int -> Stream a -> Stream a
111188drop n xs = snd <| splitAt n xs
112189
113−{-| Combination of take and drop.
190+{-| Combination of `take` and `drop`
114191
115− splitAt n xs == (take n xs, drop n xs)
192+```haskell
193+splitAt n xs == (take n xs, drop n xs)
194+```
116195-}
117196splitAt : Int -> Stream a -> ([a], Stream a)
118197splitAt n xs = case n of
@@ -121,48 +200,70 @@ splitAt n xs = case n of
121200 in (head xs :: heads, end)
122201
123202{-| Turn a stream into a signal of the elements of the stream,
124− advancing through the stream whenever an event in the given signal is
125− fired.
203+advancing through the stream whenever an event in the given signal is
204+fired.
126205-}
127206sampleOn : Signal b -> Stream a -> Signal a
128207sampleOn sig str = let tails = foldp (\_ -> tail) str sig in
129208 head <~ tails
130209
131210{-| Filter the elements of a Stream according to a predicate.
132− The produced Stream will go into an infinite loop under head or tail
133− unless there are infinitely many terms in the Stream that satisfy the
134− predicate.
211+
212+```haskell
213+-- 1, 3, 5, 7, ...
214+filter isOdd naturals
215+
216+-- Bad! Infinite loop!
217+filter isOdd twos
218+```
219+
220+The produced Stream can go into an infinite loop if no more elements
221+satisfy the predicate. So be sure that there are infinitely many terms
222+in the stream that satisfy the predicate.
135223-}
136224filter : (a -> Bool) -> Stream a -> Stream a
137−filter p xs = cons' <| (\() ->
225+filter pred xs = cons' <| (\() ->
138226 let (hd, tl) = unS xs in
139− case p hd of
140− True -> (hd, filter p tl)
141− False -> unS <| filter p tl)
227+ case pred hd of
228+ True -> (hd, filter pred tl)
229+ False -> unS <| filter pred tl)
230+
231+{-| Take values from the stream for as long as the predicate holds.
232+This can infinite loop if all elements of the stream satisfy the predicate!
142233
143−{-| Take the longest prefix of a Stream for which a predicate holds on every element.
144− This function only terminates if there is an element of the stream for
145− which the predicate does not hold.
234+```haskell
235+takeWhile (\n -> n < 10) powersOf2 == [2,4,8]
236+
237+-- Bad! Infinite loop!
238+takeWhile isEven powersOf2
239+```
146240-}
147241takeWhile : (a -> Bool) -> Stream a -> [a]
148−takeWhile p xs = fst <| splitWhen p xs
242+takeWhile pred xs = fst <| splitWith pred xs
243+
244+{-| Drop values from the stream as long as the predicate holds.
245+This can infinite loop if all elements of the stream satisfy the predicate!
246+
247+```haskell
248+-- 16, 32, 64, 128, ...
249+dropWhile (\n -> n < 10) powersOf2
149250
150−{-| Take the first tail of a Stream for which a predicate does not
151− hold on its head. This function only terminates if there is an element
152− of the stream for which the predicate does not hold.
251+-- Bad! Infinite loop!
252+dropWhile isEven powersOf2
253+```
153254-}
154255dropWhile : (a -> Bool) -> Stream a -> Stream a
155−dropWhile p xs = snd <| splitWhen p xs
256+dropWhile pred xs = snd <| splitWith pred xs
156257
157−{-| Split a Stream into its longest prefix for which a predicate holds and
158− the rest of the Stream. This function only terminates if there is an element
159− of the stream for which the predicate does not hold.
258+{-| Split a stream when a predicate holds and
259+the rest of the Stream. This function only terminates if there is
260+an element of the stream for which the predicate does not hold.
160261
161− splitWhen p xs == (takeWhile p xs, dropWhile p xs)
262+ splitWith pred xs == (takeWhile pred xs, dropWhile pred xs)
162263-}
163−splitWhen : (a -> Bool) -> Stream a -> ([a], Stream a)
164−splitWhen p xs = let (hd, tl) = unS xs in
165− case p hd of
166− True -> let (taken, dropped) = splitWhen p tl
264+splitWith : (a -> Bool) -> Stream a -> ([a], Stream a)
265+splitWith pred xs = let (hd, tl) = unS xs in
266+ case pred hd of
267+ True -> let (taken, dropped) = splitWith pred tl
167268 in (hd :: taken, dropped)
168269 False -> ([], xs)