1module Control.Stream.Stream
10 , createEventCombinator
27 , mergeMapConcurrently
56import Control.Alternative (class Apply)
57import Control.Bind (class Bind)
58import Control.Category (id)
59import Control.Monad.Eff (Eff, Pure, runPure)
60import Control.Monad.Eff.Ref (Ref, modifyRef', newRef, readRef)
61import Control.Monad.Eff.Unsafe (unsafeCoerceEff, unsafePerformEff)
62import Control.MonadPlus (class Alt, class Alternative, class MonadPlus, class Plus)
63import Control.MonadZero (class Applicative, class MonadZero)
64import Control.Stream.Disposable (Disposable, emptyDisposable, disposeAll)
65import Control.Stream.Scheduler (Scheduler(..), endTask, eventTask, scheduleTasks)
66import Control.Stream.Sink (Sink(..))
67import Control.Stream.Stream (Stream(..), EffStream, empty, just)
68import Control.Stream.Time (Time)
70import Data.EuclideanRing ((-))
71import Data.Functor (class Functor)
72import Data.Maybe (Maybe(..), fromJust, isNothing)
73import Data.Monoid (class Monoid)
74import Data.Unit (Unit, unit)
75import Partial.Unsafe (unsafePartial)
76import Prelude (class Eq, class Monad, class Semigroup, eq)
78foreign import data STREAM :: !
80type EffStream e a = Eff (stream :: STREAM | e) a
82foreign import data Subject :: * -> *
84newtype Stream a = Stream { run :: Sink a -> Scheduler -> Disposable }
86instance functorStream :: Functor Stream where
89instance applyStream :: Apply Stream where
92instance applicativeStream :: Applicative Stream where
95instance bindStream :: Bind Stream where
98instance monadStream :: Monad Stream
100instance semigroupStream :: Semigroup (Stream a) where
103instance altStream :: Alt Stream where
104 alt = \s1 s2 -> merge [s1, s2]
106instance monoidStream :: Monoid (Stream a) where
109instance plusStream :: Plus Stream where
112instance alternativeStream :: Alternative Stream
114instance monadZeroStream :: MonadZero Stream
116instance monadPlusStream :: MonadPlus Stream
118just :: forall a. a -> Stream a
119just a = Stream { run } where
120 run :: Sink a -> Scheduler -> Disposable
121 run sink (Scheduler scheduler) =
122 scheduleTasks scheduler.asap [ (eventTask sink a), (endTask sink) ]
124empty :: forall a. Stream a
125empty = Stream { run } where
126 run :: Sink a -> Scheduler -> Disposable
127 run sink (Scheduler scheduler) = scheduleTasks scheduler.asap [ endTask sink ]
129never :: forall a. Stream a
130never = Stream { run: \sink scheduler -> emptyDisposable }
132periodic :: Number -> Stream Unit
133periodic period = Stream { run } where
134 run :: Sink Unit -> Scheduler -> Disposable
135 run sink (Scheduler scheduler) = do
136 let task = eventTask sink unit
137 let scheduledTask = scheduler.periodic period task
138 { dispose : scheduledTask.dispose }
140createCombinator :: forall a b. (Sink b -> Time -> a -> Unit) -> (Sink b -> Time -> Unit) -> Stream a -> Stream b
141createCombinator event end (Stream stream) = Stream { run } where
142 run :: Sink b -> Scheduler -> Disposable
143 run sink scheduler = stream.run (Sink { event: (event sink), end: (end sink) }) scheduler
145createEventCombinator :: forall a b. (Sink b -> Time -> a -> Unit) -> Stream a -> Stream b
146createEventCombinator event stream = createCombinator event end stream where
147 end (Sink sink) time = sink.end time
149createEndCombinator :: forall a. (Sink a -> Time -> Unit) -> Stream a -> Stream a
150createEndCombinator end stream = createCombinator event end stream where
151 event (Sink sink) time value = sink.event time value
153tapEvent :: forall e a. (a -> Eff e Unit) -> Stream a -> Stream a
154tapEvent f stream = createEventCombinator event stream where
155 event :: Sink a -> Time -> a -> Unit
156 event (Sink sink) time value = sink.event time (always value (unsafePerformEff (f value)))
158tapEnd :: forall e a. Eff e Unit -> Stream a -> Stream a
159tapEnd f stream = createEndCombinator end stream where
160 end :: Sink a -> Time -> Unit
161 end (Sink sink) time = sink.end (always time (unsafePerformEff f))
163take :: forall a. Int -> Stream a -> Stream a
165take amount (Stream stream) = Stream { run } where
166 run (Sink sink) scheduler = disposable where
167 disposable = stream.run (Sink { event, end }) scheduler where
169 state = createState amount
171 event ::Time -> a -> Unit
172 event time value = do
173 let amountLeft = (getState state)
177 let newAmountLeft = state.set \x -> x - 1
178 let x = sink.event time value
179 if newAmountLeft == 0
180 then sink.end (always time (runPure disposable.dispose))
183 end time = sink.end time
185skip :: forall a. Int -> Stream a -> Stream a
186skip 0 stream = stream
187skip amount stream = createEventCombinator event stream where
189 state = createState amount
191 event :: Sink a -> Time -> a -> Unit
192 event (Sink sink) time value = do
193 let amountLeft = runPure state.get
195 then sink.event time value
196 else always unit (state.set \x -> x - 1)
198mapStream :: forall a b. (a -> b) -> Stream a -> Stream b
199mapStream f stream = createEventCombinator event stream where
200 event :: Sink b -> Time -> a -> Unit
201 event (Sink sink) time value = sink.event time (f value)
203filter :: forall a. (a -> Boolean) -> Stream a -> Stream a
204filter predicate stream = createEventCombinator event stream where
205 event (Sink sink) time value = if predicate value
206 then sink.event time value
209skipRepeatsWith :: forall a. (a -> a -> Boolean) -> Stream a -> Stream a
210skipRepeatsWith compare stream = createEventCombinator event stream where
211 state :: State (Maybe a)
212 state = createState Nothing
214 event (Sink sink) time value = do
215 let currentState = (getState state)
216 if (isNothing currentState)
217 then sink.event time value
219 let currentValue = unsafePartial (fromJust currentState)
220 if (compare currentValue value)
222 else sink.event time value
224skipRepeats :: forall a. (Eq a) => Stream a -> Stream a
225skipRepeats = skipRepeatsWith (eq)
227constant :: forall a b. b -> Stream a -> Stream b
228constant b stream = createEventCombinator event stream where
229 event :: Sink b -> Time -> a -> Unit
230 event (Sink sink) time value = sink.event time b
232concat :: forall a. Stream a -> Stream a -> Stream a
233concat s1 s2 = continueWith(\_ -> s2) s1
235startWith :: forall a. a -> Stream a -> Stream a
236startWith seed stream = concat (just seed) stream
238scan :: forall a b. (b -> a -> b) -> b -> Stream a -> Stream b
239scan f initial stream = startWith initial (createEventCombinator event stream) where
241 seed = createState initial
243 event :: Sink b -> Time -> a -> Unit
244 event (Sink sink) time value = sink.event time (seed.set \x -> f x value)
246loop :: forall a b c. (b -> a -> { seed :: b, value :: c }) -> b -> Stream a -> Stream c
247loop f initial stream = createEventCombinator event stream where
249 seed = createState initial
251 event :: Sink c -> Time -> a -> Unit
252 event (Sink sink) time x = do
253 let seedValue = f (getState seed) x
254 sink.event time (always seedValue.value (seed.set \_ -> seedValue.seed))
256concatMap :: forall a b. (a -> Stream b) -> Stream a -> Stream b
257concatMap f stream = mergeMapConcurrently f 1 stream
259ap :: forall a b. (Stream (a -> b)) -> Stream a -> Stream b
260ap fs xs = combine2 (\f x -> f x) fs xs
262during :: forall a b. Stream (Stream b) -> Stream a -> Stream a
263during timeWindow stream = until (join timeWindow) (since timeWindow stream)
265sample :: forall a b c. (a -> b -> c) -> Stream a -> Stream b -> Stream c
266sample f (Stream sampler) (Stream stream) = Stream { run: runSample (createState Nothing) } where
267 runSample :: State (Maybe b) -> Sink c -> Scheduler -> Disposable
268 runSample state sink scheduler = disposeAll
269 [ stream.run (createHoldSink state) scheduler
270 , sampler.run (createSampleSink state sink f) scheduler
273createHoldSink :: forall a. State (Maybe a) -> Sink a
274createHoldSink state = Sink { event, end } where
275 event time value = always unit (state.set \_ -> Just value)
278createSampleSink :: forall a b c. State (Maybe b) -> Sink c -> (a -> b -> c) -> Sink a
279createSampleSink state (Sink sink) f = Sink { event, end } where
280 end time = sink.end time
282 if isNothing (runPure state.get)
284 else sink.event time (f value (unsafePartial (fromJust (runPure state.get))))
286sampleWith :: forall a b. Stream b -> Stream a -> Stream a
287sampleWith signal stream = sample (\_ y -> y) signal stream
289-- find a better way to perform these side effects
290always :: forall a b. a -> b -> a
293type State a = { get:: Pure a, set :: (a -> a) -> a }
295getState :: forall a. State a -> a
296getState state = runPure state.get
298createState :: forall a. a -> State a
299createState seed = { set, get }
302 ref = unsafePerformEff (unsafeCoerceEff (newRef seed))
305 set f = unsafePerformEff (unsafeCoerceEff (modifyRef' ref \x -> { state: (f x), value: (f x) }))
308 get = unsafeCoerceEff (readRef ref)
310foreign import drain :: forall e a. Stream a -> EffStream e Unit
311foreign import subscribe :: forall e a. (a -> Eff e Unit) -> (Unit -> Eff e Unit) -> Stream a -> EffStream e Unit
312foreign import fromArray :: forall a b. Array a -> Stream b -> Stream a
313foreign import chain :: forall a b. Stream a -> (a -> Stream b) -> Stream b
314foreign import mergeConcurrently :: forall a. Int -> Stream (Stream a) -> Stream a
315foreign import join :: forall a. Stream (Stream a) -> Stream a
316foreign import mergeMapConcurrently :: forall a b. (a -> Stream b) -> Int -> Stream a -> Stream b
317foreign import switch :: forall a. Stream (Stream a) -> Stream a
318foreign import continueWith :: forall a. (Unit -> Stream a) -> Stream a -> Stream a
319foreign import combine2 :: forall a b c. (a -> b -> c) -> Stream a -> Stream b -> Stream c
320foreign import combine3 :: forall a b c d. (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
321foreign import combine4 :: forall a b c d e. (a -> b -> c -> d -> e) -> Stream a -> Stream b -> Stream c -> Stream d -> Stream e
322foreign 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
323foreign import combineArray :: forall a. Array (Stream a) -> Stream (Array a)
324foreign import merge :: forall a. Array (Stream a) -> Stream a
325foreign import until :: forall a b. Stream b -> Stream a -> Stream a
326foreign import since :: forall a b. Stream b -> Stream a -> Stream a
327foreign import debounce :: forall a. Number -> Stream a -> Stream a
328foreign import throttle :: forall a. Number -> Stream a -> Stream a
329foreign import delay :: forall a. Number -> Stream a -> Stream a
330foreign import multicast :: forall a. Stream a -> Stream a
331foreign import hold :: forall a. Stream a -> Stream a
332foreign import proxy :: forall a. a -> { attach :: (Stream a -> Stream a), stream :: Stream a }
334-- Sad subject types :/
335foreign import toSubject :: forall a. Stream a -> Subject a
336foreign import toHoldSubject :: forall a. Int -> Stream a -> Subject a
337foreign import fromSubject :: forall a. Subject a -> Stream a
338foreign import subjectEvent :: forall a. a -> Subject a -> Subject a
339foreign 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