@@ -0,0 +1,125 @@
1+module Lazy.Stream ( head, tail
2+ , cons, cons', iterate, repeat, cycle
3+ , map, apply, zip, zipWith, scanl
4+ , take, drop, splitAt
5+ , sampleOn
6+ ) where
7+
8+{-| Library for Infinite Streams
9+
10+# Create
11+@docs cons, cons', iterate, repeat, cycle
12+
13+# Observe
14+@docs head, tail, sampleOn, take, drop, splitAt
15+
16+# Transform
17+@docs map, apply, zip, zipWith, scanl
18+
19+-}
20+
21+import Basics ((.), (<|), (-), id, fst, snd)
22+import open Lazy
23+import Signal ((<~), foldp, Signal)
24+
25+data Stream a = S (Lazy (a, Stream a))
26+
27+unS : Stream a -> (a, Stream a)
28+unS (S t) = force t
29+
30+{-| Compute the first element of a Stream -}
31+head : Stream a -> a
32+head = fst . unS
33+
34+{-| Compute the next piece of a Stream -}
35+tail : Stream a -> Stream a
36+tail = snd . unS
37+
38+{-| Create a Stream -}
39+cons : a -> (() -> Stream a) -> Stream a
40+cons x txs = let mtxs = lazy txs in
41+ S . lazy <| \() ->
42+ (x, force mtxs)
43+
44+{-| Lazily create a Stream. -}
45+cons' : (() -> (a, Stream a)) -> Stream a
46+cons' = S . lazy
47+
48+{-| Create a stream of repeated applications of f to x:
49+
50+ iterate f x = S.cons x (S.cons (f x) (S.cons (f (f x)) ...))
51+-}
52+iterate : (a -> a) -> a -> Stream a
53+iterate f x = cons' <| \() ->
54+ (x, iterate f (f x))
55+
56+{-| Create an infinite Stream of xs. -}
57+repeat : a -> Stream a
58+repeat x = let go = cons x <| \() -> go
59+ in go
60+
61+{-| Cycle through the elements of the nonempty list (x :: xs) -}
62+cycle : a -> [a] -> Stream a
63+cycle x xs = let cycle' ys = case ys of
64+ [] -> go
65+ (y :: ys) -> cons y <| \() ->
66+ cycle' ys
67+ go = cons' <| \() ->
68+ (x, cycle' xs)
69+ in go
70+
71+{-| Apply a function to every element of a Stream. -}
72+map : (a -> b) -> Stream a -> Stream b
73+map f xs = cons' <| \() ->
74+ (f (head xs), map f (tail xs))
75+
76+{-| Pairwise apply a stream of functions to a stream of inputs.
77+ Together with map, generalizes zipWith to n arguments.
78+
79+ zipWith2 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
80+ zipWith2 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
81+-}
82+apply : Stream (a -> b) -> Stream a -> Stream b
83+apply fs xs = zipWith (<|) fs xs
84+
85+{-| Combine two streams, combining them into tuples pairwise. -}
86+zip : Stream a -> Stream b -> Stream (a, b)
87+zip = zipWith (\x y -> (x,y))
88+
89+{-| Combine two streams, combining them with the given function. -}
90+zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
91+zipWith f xs ys = cons' <| \() ->
92+ (f (head xs) (head ys),
93+ zipWith f (tail xs) (tail ys))
94+
95+{-| Reduce a Stream from the left, building an infinite stream of reductions. -}
96+scanl : (a -> b -> b) -> b -> Stream a -> Stream b
97+scanl f init xs = cons' <| \() ->
98+ (init,
99+ scanl f (f (head xs) init) (tail xs))
100+
101+{-| Compute the first n elements of a stream into a list. -}
102+take : Int -> Stream a -> [a]
103+take n xs = fst <| splitAt n xs
104+
105+{-| Drop n elements from the front of a stream. -}
106+drop : Int -> Stream a -> Stream a
107+drop n xs = snd <| splitAt n xs
108+
109+{-| Combination of take and drop.
110+
111+ splitAt n xs == (take n xs, drop n xs)
112+-}
113+splitAt : Int -> Stream a -> ([a], Stream a)
114+splitAt n xs = case n of
115+ 0 -> ([], xs)
116+ n -> let (heads, end) = splitAt (n - 1) (tail xs)
117+ in (head xs :: heads, end)
118+
119+{-| Turn a stream into a signal of the elements of the stream,
120+ advancing through the stream whenever an event in the given signal is
121+ fired.
122+-}
123+sampleOn : Signal b -> Stream a -> Signal a
124+sampleOn sig str = let tails = foldp (\_ -> tail) str sig in
125+ head <~ tails