1module Control.Stream.Stream
10 , createEventCombinator
28 , mergeMapConcurrently
57import Control.Alternative (class Apply)
58import Control.Bind (class Bind)
59import Control.Category (id)
60import Control.Monad.Eff (Eff, Pure, runPure)
61import Control.Monad.Eff.Ref (Ref, modifyRef', newRef, readRef)
62import Control.Monad.Eff.Unsafe (unsafeCoerceEff, unsafePerformEff)
63import Control.MonadPlus (class Alt, class Alternative, class MonadPlus, class Plus)
64import Control.MonadZero (class Applicative, class MonadZero)
65import Control.Stream.Disposable (Disposable, emptyDisposable, disposeAll)
66import Control.Stream.Scheduler (Scheduler(..), endTask, eventTask, scheduleTasks)
67import Control.Stream.Sink (Sink(..))
68import Control.Stream.Stream (Stream(..), EffStream, empty, just)
69import Control.Stream.Time (Time)
71import Data.EuclideanRing ((-))
72import Data.Functor (class Functor)
73import Data.Maybe (Maybe(..), fromJust, isNothing)
74import Data.Monoid (class Monoid)
75import Data.Unit (Unit, unit)
76import Partial.Unsafe (unsafePartial)
77import Prelude (class Eq, class Monad, class Semigroup, eq)
79foreign import data STREAM :: !
81type EffStream e a = Eff (stream :: STREAM | e) a
83foreign import data Subject :: * -> *
85newtype Stream a = Stream { run :: Sink a -> Scheduler -> Disposable }
87instance functorStream :: Functor Stream where
90instance applyStream :: Apply Stream where
93instance applicativeStream :: Applicative Stream where
96instance bindStream :: Bind Stream where
99instance monadStream :: Monad Stream
101instance semigroupStream :: Semigroup (Stream a) where
104instance altStream :: Alt Stream where
105 alt = \s1 s2 -> merge [s1, s2]
107instance monoidStream :: Monoid (Stream a) where
110instance plusStream :: Plus Stream where
113instance alternativeStream :: Alternative Stream
115instance monadZeroStream :: MonadZero Stream
117instance monadPlusStream :: MonadPlus Stream
119just :: forall a. a -> Stream a
120just a = Stream { run } where
121 run :: Sink a -> Scheduler -> Disposable
122 run sink (Scheduler scheduler) =
123 scheduleTasks scheduler.asap [ (eventTask sink a), (endTask sink) ]
125empty :: forall a. Stream a
126empty = Stream { run } where
127 run :: Sink a -> Scheduler -> Disposable
128 run sink (Scheduler scheduler) = scheduleTasks scheduler.asap [ endTask sink ]
130never :: forall a. Stream a
131never = Stream { run: \sink scheduler -> emptyDisposable }
133periodic :: Number -> Stream Unit
134periodic period = Stream { run } where
135 run :: Sink Unit -> Scheduler -> Disposable
136 run sink (Scheduler scheduler) = do
137 let task = eventTask sink unit
138 let scheduledTask = scheduler.periodic period task
139 { dispose : scheduledTask.dispose }
141createCombinator :: forall a b. (Sink b -> Time -> a -> Unit) -> (Sink b -> Time -> Unit) -> Stream a -> Stream b
142createCombinator event end (Stream stream) = Stream { run } where
143 run :: Sink b -> Scheduler -> Disposable
144 run sink scheduler = stream.run (Sink { event: (event sink), end: (end sink) }) scheduler
146createEventCombinator :: forall a b. (Sink b -> Time -> a -> Unit) -> Stream a -> Stream b
147createEventCombinator event stream = createCombinator event end stream where
148 end (Sink sink) time = sink.end time
150createEndCombinator :: forall a. (Sink a -> Time -> Unit) -> Stream a -> Stream a
151createEndCombinator end stream = createCombinator event end stream where
152 event (Sink sink) time value = sink.event time value
154tapEvent :: forall e a. (a -> Eff e Unit) -> Stream a -> Stream a
155tapEvent f stream = createEventCombinator event stream where
156 event :: Sink a -> Time -> a -> Unit
157 event (Sink sink) time value = sink.event time (always value (unsafePerformEff (f value)))
159tapEnd :: forall e a. Eff e Unit -> Stream a -> Stream a
160tapEnd f stream = createEndCombinator end stream where
161 end :: Sink a -> Time -> Unit
162 end (Sink sink) time = sink.end (always time (unsafePerformEff f))
164take :: forall a. Int -> Stream a -> Stream a
166take amount (Stream stream) = Stream { run } where
167 run (Sink sink) scheduler = disposable where
168 disposable = stream.run (Sink { event, end }) scheduler where
170 state = createState amount
172 event ::Time -> a -> Unit
173 event time value = do
174 let amountLeft = (getState state)
178 let newAmountLeft = state.set \x -> x - 1
179 let x = sink.event time value
180 if newAmountLeft == 0
181 then sink.end (always time (runPure disposable.dispose))
184 end time = sink.end time
186skip :: forall a. Int -> Stream a -> Stream a
187skip 0 stream = stream
188skip amount stream = createEventCombinator event stream where
190 state = createState amount
192 event :: Sink a -> Time -> a -> Unit
193 event (Sink sink) time value = do
194 let amountLeft = runPure state.get
196 then sink.event time value
197 else always unit (state.set \x -> x - 1)
199mapStream :: forall a b. (a -> b) -> Stream a -> Stream b
200mapStream f stream = createEventCombinator event stream where
201 event :: Sink b -> Time -> a -> Unit
202 event (Sink sink) time value = sink.event time (f value)
204filter :: forall a. (a -> Boolean) -> Stream a -> Stream a
205filter predicate stream = createEventCombinator event stream where
206 event (Sink sink) time value = if predicate value
207 then sink.event time value
210skipRepeatsWith :: forall a. (a -> a -> Boolean) -> Stream a -> Stream a
211skipRepeatsWith compare stream = createEventCombinator event stream where
212 state :: State (Maybe a)
213 state = createState Nothing
215 event (Sink sink) time value = do
216 let currentState = (getState state)
217 if (isNothing currentState)
218 then sink.event time value
220 let currentValue = unsafePartial (fromJust currentState)
221 if (compare currentValue value)
223 else sink.event time value
225skipRepeats :: forall a. (Eq a) => Stream a -> Stream a
226skipRepeats = skipRepeatsWith (eq)
228constant :: forall a b. b -> Stream a -> Stream b
229constant b stream = createEventCombinator event stream where
230 event :: Sink b -> Time -> a -> Unit
231 event (Sink sink) time value = sink.event time b
233concat :: forall a. Stream a -> Stream a -> Stream a
234concat s1 s2 = continueWith(\_ -> s2) s1
236startWith :: forall a. a -> Stream a -> Stream a
237startWith seed stream = concat (just seed) stream
239scan :: forall a b. (b -> a -> b) -> b -> Stream a -> Stream b
240scan f initial stream = startWith initial (createEventCombinator event stream) where
242 seed = createState initial
244 event :: Sink b -> Time -> a -> Unit
245 event (Sink sink) time value = sink.event time (seed.set \x -> f x value)
247loop :: forall a b c. (b -> a -> { seed :: b, value :: c }) -> b -> Stream a -> Stream c
248loop f initial stream = createEventCombinator event stream where
250 seed = createState initial
252 event :: Sink c -> Time -> a -> Unit
253 event (Sink sink) time x = do
254 let seedValue = f (getState seed) x
255 sink.event time (always seedValue.value (seed.set \_ -> seedValue.seed))
257concatMap :: forall a b. (a -> Stream b) -> Stream a -> Stream b
258concatMap f stream = mergeMapConcurrently f 1 stream
260ap :: forall a b. (Stream (a -> b)) -> Stream a -> Stream b
261ap fs xs = combine2 (\f x -> f x) fs xs
263during :: forall a b. Stream (Stream b) -> Stream a -> Stream a
264during timeWindow stream = until (join timeWindow) (since timeWindow stream)
266sample :: forall a b c. (a -> b -> c) -> Stream a -> Stream b -> Stream c
267sample f (Stream sampler) (Stream stream) = Stream { run: runSample (createState Nothing) } where
268 runSample :: State (Maybe b) -> Sink c -> Scheduler -> Disposable
269 runSample state sink scheduler = disposeAll
270 [ stream.run (createHoldSink state) scheduler
271 , sampler.run (createSampleSink state sink f) scheduler
274createHoldSink :: forall a. State (Maybe a) -> Sink a
275createHoldSink state = Sink { event, end } where
276 event time value = always unit (state.set \_ -> Just value)
279createSampleSink :: forall a b c. State (Maybe b) -> Sink c -> (a -> b -> c) -> Sink a
280createSampleSink state (Sink sink) f = Sink { event, end } where
281 end time = sink.end time
283 if isNothing (runPure state.get)
285 else sink.event time (f value (unsafePartial (fromJust (runPure state.get))))
287sampleWith :: forall a b. Stream b -> Stream a -> Stream a
288sampleWith signal stream = sample (\_ y -> y) signal stream
290-- find a better way to perform these side effects
291always :: forall a b. a -> b -> a
294type State a = { get:: Pure a, set :: (a -> a) -> a }
296getState :: forall a. State a -> a
297getState state = runPure state.get
299createState :: forall a. a -> State a
300createState seed = { set, get }
303 ref = unsafePerformEff (unsafeCoerceEff (newRef seed))
306 set f = unsafePerformEff (unsafeCoerceEff (modifyRef' ref \x -> { state: (f x), value: (f x) }))
309 get = unsafeCoerceEff (readRef ref)
311foreign import drain :: forall e a. Stream a -> EffStream e Unit
312foreign import subscribe :: forall e a. (a -> Eff e Unit) -> (Unit -> Eff e Unit) -> Stream a -> EffStream e Unit
313foreign import fromArray :: forall a b. Array a -> Stream b -> Stream a
314foreign import chain :: forall a b. Stream a -> (a -> Stream b) -> Stream b
315foreign import mergeConcurrently :: forall a. Int -> Stream (Stream a) -> Stream a
316foreign import join :: forall a. Stream (Stream a) -> Stream a
317foreign import mergeMapConcurrently :: forall a b. (a -> Stream b) -> Int -> Stream a -> Stream b
318foreign import switch :: forall a. Stream (Stream a) -> Stream a
319foreign import continueWith :: forall a. (Unit -> Stream a) -> Stream a -> Stream a
320foreign import combine2 :: forall a b c. (a -> b -> c) -> Stream a -> Stream b -> Stream c
321foreign import combine3 :: forall a b c d. (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
322foreign import combine4 :: forall a b c d e. (a -> b -> c -> d -> e) -> Stream a -> Stream b -> Stream c -> Stream d -> Stream e
323foreign import combine5 :: forall a b c d e f. (a -> b -> c -> d -> e -> f) -> Stream a -> Stream b -> Stream c -> Stream d -> Stream e -> Stream f
324foreign import combineArray :: forall a. Array (Stream a) -> Stream (Array a)
325foreign import merge :: forall a. Array (Stream a) -> Stream a
326foreign import until :: forall a b. Stream b -> Stream a -> Stream a
327foreign import since :: forall a b. Stream b -> Stream a -> Stream a
328foreign import debounce :: forall a. Number -> Stream a -> Stream a
329foreign import throttle :: forall a. Number -> Stream a -> Stream a
330foreign import delay :: forall a. Number -> Stream a -> Stream a
331foreign import multicast :: forall a. Stream a -> Stream a
332foreign import hold :: forall a. Stream a -> Stream a
333foreign import proxy :: forall a. a -> { attach :: (Stream a -> Stream a), stream :: Stream a }
335-- Sad subject types :/
336foreign import toSubject :: forall a. Stream a -> Subject a
337foreign import toHoldSubject :: forall a. Int -> Stream a -> Subject a
338foreign import fromSubject :: forall a. Subject a -> Stream a
339foreign import subjectEvent :: forall a. a -> Subject a -> Subject a
340foreign import subjectEnd :: forall a. a -> Subject a -> Subject a
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list