on 20a140f help sign in
streamly/src/Streamly/Streams.hs
921 lines 33 kB history raw
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving#-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE RankNTypes #-}
6{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE UndecidableInstances #-} -- XXX
9-- |
10-- Module : Streamly.Streams
11-- Copyright : (c) 2017 Harendra Kumar
12--
13-- License : BSD3
14-- Maintainer : harendra.kumar@gmail.com
15-- Stability : experimental
16-- Portability : GHC
17--
18--
19module Streamly.Streams
20 (
21 -- * Product Style Composition
22 -- $product
23 Streaming (..)
24 , MonadAsync
26 -- * SVars
27 , SVarSched (..)
28 , SVarTag (..)
29 , SVarStyle (..)
30 , SVar
31 , newEmptySVar
33 -- * Construction
34 , streamBuild
35 , fromCallback
36 , fromSVar
38 -- * Elimination
39 , cons
40 , nil
41 , streamFold
42 , runStreaming
43 , toSVar
45 -- * Transformation
46 , async
48 -- * Stream Styles
49 , StreamT
50 , InterleavedT
51 , AsyncT
52 , ParallelT
53 , ZipStream
54 , ZipAsync
56 -- * Type Adapters
57 , serially
58 , interleaving
59 , asyncly
60 , parallely
61 , zipping
62 , zippingAsync
63 , adapt
65 -- * Running Streams
66 , runStreamT
67 , runInterleavedT
68 , runAsyncT
69 , runParallelT
70 , runZipStream
71 , runZipAsync
73 -- * Zipping
74 , zipWith
75 , zipAsyncWith
77 -- * Sum Style Composition
78 , (<=>)
79 , (<|)
81 -- * Fold Utilities
82 -- $foldutils
83 , foldWith
84 , foldMapWith
85 , forEachWith
86 )
87where
89import Control.Applicative (Alternative (..), liftA2)
90import Control.Monad (MonadPlus(..), ap)
91import Control.Monad.Base (MonadBase (..))
92import Control.Monad.Catch (MonadThrow)
93import Control.Monad.Error.Class (MonadError(..))
94import Control.Monad.IO.Class (MonadIO(..))
95import Control.Monad.Reader.Class (MonadReader(..))
96import Control.Monad.State.Class (MonadState(..))
97import Control.Monad.Trans.Class (MonadTrans)
98import Data.Semigroup (Semigroup(..))
99import Prelude hiding (drop, take, zipWith)
100import Streamly.Core
102-- $product
103--
104-- Different styles of streams represented by different types dictate the
105-- manner in which a stream is processed in monadic or applicative composition.
106-- Each type differs in the processing order of the elements or processing
107-- parallelism. The types have the same underlying representation and
108-- therefore can be converted back and forth easily to switch the composition
109-- style at any point.
110--
111-- 'StreamT' and 'InterleavedT' process the streams serially but differ in the
112-- order in which the elements of the streams are processed. 'StreamT' goes
113-- depth first that is it combine one element of the first stream to every
114-- element of the second stream before it comes back to process the second
115-- element of the first stream. 'InterleavedT' takes turns when processing
116-- elements from each stream and therefore all iterations finish at the same
117-- time rather than one iteration at a time as in the case of 'StreamT'.
118-- Depending on the cache behavior or IO behavior 'InterleavedT' might be
119-- slightly more efficient than 'StreamT' or vice-versa.
120--
121-- 'AsyncT' and 'ParallelT' can process the individual elements of the streams
122-- in parallel. 'AsyncT' is the parallel version of 'StreamT', it follows the
123-- order of 'StreamT', processing multiple elements of a stream concurrently.
124-- 'ParallelT' follows the order of 'InterleavedT', processing and interleaving
125-- both streams concurrently. Also, note that 'fmap' on these streams would
126-- also work in a concurrent fashion i.e. multiple elements in a stream or
127-- multiple streams can be mapped concurrently.
128--
129-- Zipping types have a different style of composition altogether, they zip the
130-- streams rather than multiplying them. These types provide only Applicative
131-- composition and no Monad instances. 'ZipStream' zips serially i.e. it
132-- produces one element from each stream in a serial manner and then zips the
133-- two items. 'ZipAsync' on the other hand zips in parallel, it produces one
134-- element from each stream concurrently and then zips the two.
135--
136-- It may help develop a better understanding if we think in terms of stream
137-- generation (production) side parallelism versus stream processing
138-- (consumption) side parallelism. The sum style operators (e.g. '<|' or '<|>')
139-- generate streams in parallel and then combine the results into a unified
140-- stream. On the other hand the product style composition (e.g. 'AsyncT' or
141-- 'ParallelT' or 'ZipAsync') dictate how the elements of a stream are
142-- processed when it is consumed.
144------------------------------------------------------------------------------
145-- Types that can behave as a Stream
146------------------------------------------------------------------------------
148-- | Class of types that can represent a stream of elements of some type 'a' in
149-- some monad 'm'.
150class Streaming t where
151 toStream :: t m a -> Stream m a
152 fromStream :: Stream m a -> t m a
154------------------------------------------------------------------------------
155-- Constructing a stream
156------------------------------------------------------------------------------
158cons :: (Streaming t) => a -> t m a -> t m a
159cons a r = fromStream $ scons a (Just (toStream r))
161nil :: Streaming t => t m a
162nil = fromStream $ snil
164-- | Build a stream from its church encoding. The function passed maps
165-- directly to the underlying representation of the stream type. The second
166-- parameter to the function is the "yield" function yielding a value and the
167-- remaining stream if any otherwise 'Nothing'. The third parameter is to
168-- represent an "empty" stream.
169streamBuild :: Streaming t
170 => (forall r. Maybe (SVar m a)
171 -> (a -> Maybe (t m a) -> m r)
172 -> m r
173 -> m r)
174 -> t m a
175streamBuild k = fromStream $ Stream $ \sv stp yld ->
176 let yield a Nothing = yld a Nothing
177 yield a (Just r) = yld a (Just (toStream r))
178 in k sv yield stp
180-- | Build a singleton stream from a callback function.
181fromCallback :: (Streaming t) => (forall r. (a -> m r) -> m r) -> t m a
182fromCallback k = fromStream $ Stream $ \_ _ yld -> k (\a -> yld a Nothing)
184-- | Read an SVar to get a stream.
185fromSVar :: (MonadAsync m, Streaming t) => SVar m a -> t m a
186fromSVar sv = fromStream $ fromStreamVar sv
188------------------------------------------------------------------------------
189-- Destroying a stream
190------------------------------------------------------------------------------
192-- | Fold a stream using its church encoding. The second argument is the "step"
193-- function consuming an element and the remaining stream, if any. The third
194-- argument is for consuming an "empty" stream that yields nothing.
195streamFold :: Streaming t
196 => Maybe (SVar m a) -> (a -> Maybe (t m a) -> m r) -> m r -> t m a -> m r
197streamFold sv step blank m =
198 let yield a Nothing = step a Nothing
199 yield a (Just x) = step a (Just (fromStream x))
200 in (runStream (toStream m)) sv blank yield
202-- | Run a streaming composition, discard the results.
203runStreaming :: (Monad m, Streaming t) => t m a -> m ()
204runStreaming m = go (toStream m)
205 where
206 go m1 =
207 let stop = return ()
208 yield _ Nothing = stop
209 yield _ (Just x) = go x
210 in (runStream m1) Nothing stop yield
212-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
213-- be read back from the SVar using 'fromSVar'.
214toSVar :: (Streaming t, MonadAsync m) => SVar m a -> t m a -> m ()
215toSVar sv m = toStreamVar sv (toStream m)
217------------------------------------------------------------------------------
218-- Transformation
219------------------------------------------------------------------------------
221-- XXX Get rid of this?
222-- | Make a stream asynchronous, triggers the computation and returns a stream
223-- in the underlying monad representing the output generated by the original
224-- computation. The returned action is exhaustible and must be drained once. If
225-- not drained fully we may have a thread blocked forever and once exhausted it
226-- will always return 'empty'.
228async :: (Streaming t, MonadAsync m) => t m a -> m (t m a)
229async m = do
230 sv <- newStreamVar1 (SVarStyle Disjunction LIFO) (toStream m)
231 return $ fromSVar sv
233------------------------------------------------------------------------------
234-- StreamT iterates serially in the Monad and Applicative compositions
235------------------------------------------------------------------------------
237-- | Note that 'StreamT' style composition works well operationally for
238-- infinite streams. However if the second stream is infinite we will never
239-- come back to the second iteration of the first stream.
241newtype StreamT m a = StreamT {getStreamT :: Stream m a}
242 deriving (Semigroup, Monoid, MonadTrans, MonadIO, MonadThrow)
244deriving instance MonadAsync m => Alternative (StreamT m)
245deriving instance MonadAsync m => MonadPlus (StreamT m)
246deriving instance (MonadBase b m, Monad m) => MonadBase b (StreamT m)
247deriving instance MonadError e m => MonadError e (StreamT m)
248deriving instance MonadReader r m => MonadReader r (StreamT m)
249deriving instance MonadState s m => MonadState s (StreamT m)
251instance Streaming StreamT where
252 toStream = getStreamT
253 fromStream = StreamT
255-- XXX The Functor/Applicative/Num instances for all the types are exactly the
256-- same, how can we reduce this boilerplate (use TH)? We cannot derive them
257-- from a single base type because they depend on the Monad instance which is
258-- different for each type.
260------------------------------------------------------------------------------
261-- Monad
262------------------------------------------------------------------------------
264-- | Execute a monadic action sequentially for each element in the 'AsyncT'
265-- stream, i.e. an iteration finishes completely before the next one starts.
266instance Monad m => Monad (StreamT m) where
267 return = pure
268 (StreamT (Stream m)) >>= f = StreamT $ Stream $ \_ stp yld ->
269 let run x = (runStream x) Nothing stp yld
270 yield a Nothing = run $ getStreamT (f a)
271 yield a (Just r) = run $ getStreamT (f a)
272 <> getStreamT (StreamT r >>= f)
273 in m Nothing stp yield
275------------------------------------------------------------------------------
276-- Applicative
277------------------------------------------------------------------------------
279instance Monad m => Applicative (StreamT m) where
280 pure a = StreamT $ scons a Nothing
281 (<*>) = ap
283------------------------------------------------------------------------------
284-- Functor
285------------------------------------------------------------------------------
287instance Monad m => Functor (StreamT m) where
288 fmap f (StreamT (Stream m)) = StreamT $ Stream $ \_ stp yld ->
289 let yield a Nothing = yld (f a) Nothing
290 yield a (Just r) = yld (f a)
291 (Just (getStreamT (fmap f (StreamT r))))
292 in m Nothing stp yield
294------------------------------------------------------------------------------
295-- Num
296------------------------------------------------------------------------------
298instance (Monad m, Num a) => Num (StreamT m a) where
299 fromInteger n = pure (fromInteger n)
301 negate = fmap negate
302 abs = fmap abs
303 signum = fmap signum
305 (+) = liftA2 (+)
306 (*) = liftA2 (*)
307 (-) = liftA2 (-)
309instance (Monad m, Fractional a) => Fractional (StreamT m a) where
310 fromRational n = pure (fromRational n)
312 recip = fmap recip
314 (/) = liftA2 (/)
316instance (Monad m, Floating a) => Floating (StreamT m a) where
317 pi = pure pi
319 exp = fmap exp
320 sqrt = fmap sqrt
321 log = fmap log
322 sin = fmap sin
323 tan = fmap tan
324 cos = fmap cos
325 asin = fmap asin
326 atan = fmap atan
327 acos = fmap acos
328 sinh = fmap sinh
329 tanh = fmap tanh
330 cosh = fmap cosh
331 asinh = fmap asinh
332 atanh = fmap atanh
333 acosh = fmap acosh
335 (**) = liftA2 (**)
336 logBase = liftA2 logBase
338------------------------------------------------------------------------------
339-- InterleavedT interleaves the iterations in the Monad and Applicative
340-- compositions.
341------------------------------------------------------------------------------
343-- | Note that 'InterleavedT' style composition cannot work well operationally
344-- on infinite streams. It will keep accumulating the elements of the stream
345-- resulting in continuous increase in space consumption.
346--
347newtype InterleavedT m a = InterleavedT {getInterleavedT :: Stream m a}
348 deriving (Semigroup, Monoid, MonadTrans, MonadIO, MonadThrow)
350deriving instance MonadAsync m => Alternative (InterleavedT m)
351deriving instance MonadAsync m => MonadPlus (InterleavedT m)
352deriving instance (MonadBase b m, Monad m) => MonadBase b (InterleavedT m)
353deriving instance MonadError e m => MonadError e (InterleavedT m)
354deriving instance MonadReader r m => MonadReader r (InterleavedT m)
355deriving instance MonadState s m => MonadState s (InterleavedT m)
357instance Streaming InterleavedT where
358 toStream = getInterleavedT
359 fromStream = InterleavedT
361-- | Execute a monadic action for each element in the stream, in a fairly
362-- interleaved manner i.e. iterations yield alternately.
363instance Monad m => Monad (InterleavedT m) where
364 return = pure
365 (InterleavedT (Stream m)) >>= f = InterleavedT $ Stream $ \_ stp yld ->
366 let run x = (runStream x) Nothing stp yld
367 yield a Nothing = run $ getInterleavedT (f a)
368 yield a (Just r) = run $ getInterleavedT (f a)
369 `interleave`
370 getInterleavedT (InterleavedT r >>= f)
371 in m Nothing stp yield
373------------------------------------------------------------------------------
374-- Applicative
375------------------------------------------------------------------------------
377instance Monad m => Applicative (InterleavedT m) where
378 pure a = InterleavedT $ scons a Nothing
379 (<*>) = ap
381------------------------------------------------------------------------------
382-- Functor
383------------------------------------------------------------------------------
385instance Monad m => Functor (InterleavedT m) where
386 fmap f (InterleavedT (Stream m)) = InterleavedT $ Stream $ \_ stp yld ->
387 let yield a Nothing = yld (f a) Nothing
388 yield a (Just r) =
389 yld (f a) (Just (getInterleavedT (fmap f (InterleavedT r))))
390 in m Nothing stp yield
392------------------------------------------------------------------------------
393-- Num
394------------------------------------------------------------------------------
396instance (Monad m, Num a) => Num (InterleavedT m a) where
397 fromInteger n = pure (fromInteger n)
399 negate = fmap negate
400 abs = fmap abs
401 signum = fmap signum
403 (+) = liftA2 (+)
404 (*) = liftA2 (*)
405 (-) = liftA2 (-)
407instance (Monad m, Fractional a) => Fractional (InterleavedT m a) where
408 fromRational n = pure (fromRational n)
410 recip = fmap recip
412 (/) = liftA2 (/)
414instance (Monad m, Floating a) => Floating (InterleavedT m a) where
415 pi = pure pi
417 exp = fmap exp
418 sqrt = fmap sqrt
419 log = fmap log
420 sin = fmap sin
421 tan = fmap tan
422 cos = fmap cos
423 asin = fmap asin
424 atan = fmap atan
425 acos = fmap acos
426 sinh = fmap sinh
427 tanh = fmap tanh
428 cosh = fmap cosh
429 asinh = fmap asinh
430 atanh = fmap atanh
431 acosh = fmap acosh
433 (**) = liftA2 (**)
434 logBase = liftA2 logBase
436------------------------------------------------------------------------------
437-- AsyncT runs the iterations asynchronously in the Monad and Applicative
438-- compositions. More iterations are started in parallel on demand. It can work
439-- with infinite streams.
440------------------------------------------------------------------------------
442-- | Just like 'StreamT', 'AsyncT' style composition works well operationally
443-- for infinite streams. However, if the second stream is infinite we will
444-- never be able to finish the first stream.
445--
446-- Note that 'fmap' on 'AsyncT' would map on multiple elements concurrently.
448newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
449 deriving (Semigroup, Monoid, MonadTrans)
451deriving instance MonadAsync m => Alternative (AsyncT m)
452deriving instance MonadAsync m => MonadPlus (AsyncT m)
453deriving instance MonadAsync m => MonadIO (AsyncT m)
454deriving instance MonadAsync m => MonadThrow (AsyncT m)
455deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (AsyncT m)
456deriving instance (MonadError e m, MonadAsync m) => MonadError e (AsyncT m)
457deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (AsyncT m)
458deriving instance (MonadState s m, MonadAsync m) => MonadState s (AsyncT m)
460instance Streaming AsyncT where
461 toStream = getAsyncT
462 fromStream = AsyncT
464{-# INLINE parbind #-}
465parbind
466 :: (forall c. Stream m c -> Stream m c -> Stream m c)
467 -> Stream m a
468 -> (a -> Stream m b)
469 -> Stream m b
470parbind par m f = go m
471 where
472 go (Stream g) =
473 Stream $ \ctx stp yld ->
474 let run x = (runStream x) ctx stp yld
475 yield a Nothing = run $ f a
476 yield a (Just r) = run $ f a `par` (go r)
477 in g Nothing stp yield
479-- | Execute a monadic action for each element in the stream, running
480-- iterations in parallel, but giving preference to iterations started
481-- earlier.
482instance MonadAsync m => Monad (AsyncT m) where
483 return = pure
484 (AsyncT m) >>= f = AsyncT $ parbind par m g
485 where g x = getAsyncT (f x)
486 par = joinStreamVar2 (SVarStyle Conjunction LIFO)
488------------------------------------------------------------------------------
489-- Applicative
490------------------------------------------------------------------------------
492instance MonadAsync m => Applicative (AsyncT m) where
493 pure a = AsyncT $ scons a Nothing
494 (<*>) = ap
496------------------------------------------------------------------------------
497-- Functor
498------------------------------------------------------------------------------
500instance Monad m => Functor (AsyncT m) where
501 fmap f (AsyncT (Stream m)) = AsyncT $ Stream $ \_ stp yld ->
502 let yield a Nothing = yld (f a) Nothing
503 yield a (Just r) = yld (f a) (Just (getAsyncT (fmap f (AsyncT r))))
504 in m Nothing stp yield
506------------------------------------------------------------------------------
507-- Num
508------------------------------------------------------------------------------
510instance (MonadAsync m, Num a) => Num (AsyncT m a) where
511 fromInteger n = pure (fromInteger n)
513 negate = fmap negate
514 abs = fmap abs
515 signum = fmap signum
517 (+) = liftA2 (+)
518 (*) = liftA2 (*)
519 (-) = liftA2 (-)
521instance (MonadAsync m, Fractional a) => Fractional (AsyncT m a) where
522 fromRational n = pure (fromRational n)
524 recip = fmap recip
526 (/) = liftA2 (/)
528instance (MonadAsync m, Floating a) => Floating (AsyncT m a) where
529 pi = pure pi
531 exp = fmap exp
532 sqrt = fmap sqrt
533 log = fmap log
534 sin = fmap sin
535 tan = fmap tan
536 cos = fmap cos
537 asin = fmap asin
538 atan = fmap atan
539 acos = fmap acos
540 sinh = fmap sinh
541 tanh = fmap tanh
542 cosh = fmap cosh
543 asinh = fmap asinh
544 atanh = fmap atanh
545 acosh = fmap acosh
547 (**) = liftA2 (**)
548 logBase = liftA2 logBase
550------------------------------------------------------------------------------
551-- ParallelT runs all iterations in parallel in the Monad and Applicative
552-- compositions. Iterations are scheduled in a round-robin fashion.
553------------------------------------------------------------------------------
555-- | Note that, just like 'InterleavedT', 'ParallelT' style composition cannot
556-- work well operationally on infinite streams. It will keep accumulating the
557-- elements of the stream resulting in continuous increase in space
558-- consumption.
559--
560-- Note that 'fmap' on 'ParallelT' would map on both streams concurrently.
561--
562newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
563 deriving (Semigroup, Monoid, MonadTrans)
565deriving instance MonadAsync m => Alternative (ParallelT m)
566deriving instance MonadAsync m => MonadPlus (ParallelT m)
567deriving instance MonadAsync m => MonadIO (ParallelT m)
568deriving instance MonadAsync m => MonadThrow (ParallelT m)
569deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (ParallelT m)
570deriving instance (MonadError e m, MonadAsync m) => MonadError e (ParallelT m)
571deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (ParallelT m)
572deriving instance (MonadState s m, MonadAsync m) => MonadState s (ParallelT m)
574instance Streaming ParallelT where
575 toStream = getParallelT
576 fromStream = ParallelT
578-- | Execute a monadic action for each element in the stream, running
579-- iterations in a fairly parallel manner, i.e. all iterations are equally
580-- likely to run.
581instance MonadAsync m => Monad (ParallelT m) where
582 return = pure
583 (ParallelT m) >>= f = ParallelT $ parbind par m g
584 where g x = getParallelT (f x)
585 par = joinStreamVar2 (SVarStyle Conjunction FIFO)
587------------------------------------------------------------------------------
588-- Applicative
589------------------------------------------------------------------------------
591instance MonadAsync m => Applicative (ParallelT m) where
592 pure a = ParallelT $ scons a Nothing
593 (<*>) = ap
595------------------------------------------------------------------------------
596-- Functor
597------------------------------------------------------------------------------
599instance Monad m => Functor (ParallelT m) where
600 fmap f (ParallelT (Stream m)) = ParallelT $ Stream $ \_ stp yld ->
601 let yield a Nothing = yld (f a) Nothing
602 yield a (Just r) = yld (f a)
603 (Just (getParallelT (fmap f (ParallelT r))))
604 in m Nothing stp yield
606------------------------------------------------------------------------------
607-- Num
608------------------------------------------------------------------------------
610instance (MonadAsync m, Num a) => Num (ParallelT m a) where
611 fromInteger n = pure (fromInteger n)
613 negate = fmap negate
614 abs = fmap abs
615 signum = fmap signum
617 (+) = liftA2 (+)
618 (*) = liftA2 (*)
619 (-) = liftA2 (-)
621instance (MonadAsync m, Fractional a) => Fractional (ParallelT m a) where
622 fromRational n = pure (fromRational n)
624 recip = fmap recip
626 (/) = liftA2 (/)
628instance (MonadAsync m, Floating a) => Floating (ParallelT m a) where
629 pi = pure pi
631 exp = fmap exp
632 sqrt = fmap sqrt
633 log = fmap log
634 sin = fmap sin
635 tan = fmap tan
636 cos = fmap cos
637 asin = fmap asin
638 atan = fmap atan
639 acos = fmap acos
640 sinh = fmap sinh
641 tanh = fmap tanh
642 cosh = fmap cosh
643 asinh = fmap asinh
644 atanh = fmap atanh
645 acosh = fmap acosh
647 (**) = liftA2 (**)
648 logBase = liftA2 logBase
650------------------------------------------------------------------------------
651-- Serially Zipping Streams
652------------------------------------------------------------------------------
654-- | Zip two streams serially using a pure zipping function.
655zipWith :: Streaming t => (a -> b -> c) -> t m a -> t m b -> t m c
656zipWith f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
657 where
658 go mx my = Stream $ \_ stp yld -> do
659 let merge a ra =
660 let yield2 b Nothing = yld (f a b) Nothing
661 yield2 b (Just rb) = yld (f a b) (Just (go ra rb))
662 in (runStream my) Nothing stp yield2
663 let yield1 a Nothing = merge a snil
664 yield1 a (Just ra) = merge a ra
665 (runStream mx) Nothing stp yield1
667-- | 'ZipStream' zips serially i.e. it produces one element from each stream in
668-- a serial manner and then zips the two elements.
669newtype ZipStream m a = ZipStream {getZipStream :: Stream m a}
670 deriving (Semigroup, Monoid)
672deriving instance MonadAsync m => Alternative (ZipStream m)
674instance Monad m => Functor (ZipStream m) where
675 fmap f (ZipStream (Stream m)) = ZipStream $ Stream $ \_ stp yld ->
676 let yield a Nothing = yld (f a) Nothing
677 yield a (Just r) = yld (f a)
678 (Just (getZipStream (fmap f (ZipStream r))))
679 in m Nothing stp yield
681instance Monad m => Applicative (ZipStream m) where
682 pure a = ZipStream $ scons a Nothing
683 (<*>) = zipWith id
685instance Streaming ZipStream where
686 toStream = getZipStream
687 fromStream = ZipStream
689instance (Monad m, Num a) => Num (ZipStream m a) where
690 fromInteger n = pure (fromInteger n)
692 negate = fmap negate
693 abs = fmap abs
694 signum = fmap signum
696 (+) = liftA2 (+)
697 (*) = liftA2 (*)
698 (-) = liftA2 (-)
700instance (Monad m, Fractional a) => Fractional (ZipStream m a) where
701 fromRational n = pure (fromRational n)
703 recip = fmap recip
705 (/) = liftA2 (/)
707instance (Monad m, Floating a) => Floating (ZipStream m a) where
708 pi = pure pi
710 exp = fmap exp
711 sqrt = fmap sqrt
712 log = fmap log
713 sin = fmap sin
714 tan = fmap tan
715 cos = fmap cos
716 asin = fmap asin
717 atan = fmap atan
718 acos = fmap acos
719 sinh = fmap sinh
720 tanh = fmap tanh
721 cosh = fmap cosh
722 asinh = fmap asinh
723 atanh = fmap atanh
724 acosh = fmap acosh
726 (**) = liftA2 (**)
727 logBase = liftA2 logBase
729------------------------------------------------------------------------------
730-- Parallely Zipping Streams
731------------------------------------------------------------------------------
733-- | Zip two streams asyncly (i.e. both the elements being zipped are generated
734-- concurrently) using a pure zipping function.
735zipAsyncWith :: (Streaming t, MonadAsync m)
736 => (a -> b -> c) -> t m a -> t m b -> t m c
737zipAsyncWith f m1 m2 = fromStream $ Stream $ \_ stp yld -> do
738 ma <- async m1
739 mb <- async m2
740 (runStream (toStream (zipWith f ma mb))) Nothing stp yld
742-- | 'ZipAsync' zips in parallel, it produces one element from each stream
743-- concurrently and then zips the two.
744newtype ZipAsync m a = ZipAsync {getZipAsync :: Stream m a}
745 deriving (Semigroup, Monoid)
747deriving instance MonadAsync m => Alternative (ZipAsync m)
749instance Monad m => Functor (ZipAsync m) where
750 fmap f (ZipAsync (Stream m)) = ZipAsync $ Stream $ \_ stp yld ->
751 let yield a Nothing = yld (f a) Nothing
752 yield a (Just r) = yld (f a)
753 (Just (getZipAsync (fmap f (ZipAsync r))))
754 in m Nothing stp yield
756instance MonadAsync m => Applicative (ZipAsync m) where
757 pure a = ZipAsync $ scons a Nothing
758 (<*>) = zipAsyncWith id
760instance Streaming ZipAsync where
761 toStream = getZipAsync
762 fromStream = ZipAsync
764instance (MonadAsync m, Num a) => Num (ZipAsync m a) where
765 fromInteger n = pure (fromInteger n)
767 negate = fmap negate
768 abs = fmap abs
769 signum = fmap signum
771 (+) = liftA2 (+)
772 (*) = liftA2 (*)
773 (-) = liftA2 (-)
775instance (MonadAsync m, Fractional a) => Fractional (ZipAsync m a) where
776 fromRational n = pure (fromRational n)
778 recip = fmap recip
780 (/) = liftA2 (/)
782instance (MonadAsync m, Floating a) => Floating (ZipAsync m a) where
783 pi = pure pi
785 exp = fmap exp
786 sqrt = fmap sqrt
787 log = fmap log
788 sin = fmap sin
789 tan = fmap tan
790 cos = fmap cos
791 asin = fmap asin
792 atan = fmap atan
793 acos = fmap acos
794 sinh = fmap sinh
795 tanh = fmap tanh
796 cosh = fmap cosh
797 asinh = fmap asinh
798 atanh = fmap atanh
799 acosh = fmap acosh
801 (**) = liftA2 (**)
802 logBase = liftA2 logBase
804-------------------------------------------------------------------------------
805-- Type adapting combinators
806-------------------------------------------------------------------------------
808-- | Adapt one streaming type to another.
809adapt :: (Streaming t1, Streaming t2) => t1 m a -> t2 m a
810adapt = fromStream . toStream
812-- | Interpret an ambiguously typed stream as 'StreamT'.
813serially :: StreamT m a -> StreamT m a
814serially x = x
816-- | Interpret an ambiguously typed stream as 'InterleavedT'.
817interleaving :: InterleavedT m a -> InterleavedT m a
818interleaving x = x
820-- | Interpret an ambiguously typed stream as 'AsyncT'.
821asyncly :: AsyncT m a -> AsyncT m a
822asyncly x = x
824-- | Interpret an ambiguously typed stream as 'ParallelT'.
825parallely :: ParallelT m a -> ParallelT m a
826parallely x = x
828-- | Interpret an ambiguously typed stream as 'ZipStream'.
829zipping :: ZipStream m a -> ZipStream m a
830zipping x = x
832-- | Interpret an ambiguously typed stream as 'ZipAsync'.
833zippingAsync :: ZipAsync m a -> ZipAsync m a
834zippingAsync x = x
836-------------------------------------------------------------------------------
837-- Running Streams, convenience functions specialized to types
838-------------------------------------------------------------------------------
840-- | Run a 'StreamT' computation. Same as @runStreaming . serially@.
841runStreamT :: Monad m => StreamT m a -> m ()
842runStreamT = runStreaming
844-- | Run an 'InterleavedT' computation. Same as @runStreaming . interleaving@.
845runInterleavedT :: Monad m => InterleavedT m a -> m ()
846runInterleavedT = runStreaming
848-- | Run an 'AsyncT' computation. Same as @runStreaming . asyncly@.
849runAsyncT :: Monad m => AsyncT m a -> m ()
850runAsyncT = runStreaming
852-- | Run a 'ParallelT' computation. Same as @runStreaming . parallely@.
853runParallelT :: Monad m => ParallelT m a -> m ()
854runParallelT = runStreaming
856-- | Run a 'ZipStream' computation. Same as @runStreaming . zipping@.
857runZipStream :: Monad m => ZipStream m a -> m ()
858runZipStream = runStreaming
860-- | Run a 'ZipAsync' computation. Same as @runStreaming . zippingAsync@.
861runZipAsync :: Monad m => ZipAsync m a -> m ()
862runZipAsync = runStreaming
864------------------------------------------------------------------------------
865-- Sum Style Composition
866------------------------------------------------------------------------------
868infixr 5 <=>
870-- | Sequential interleaved composition, in contrast to '<>' this operator
871-- fairly interleaves the two streams instead of appending them; yielding one
872-- element from each stream alternately. Unlike '<>' it cannot be used to fold
873-- an infinite container of streams.
874{-# INLINE (<=>) #-}
875(<=>) :: Streaming t => t m a -> t m a -> t m a
876m1 <=> m2 = fromStream $ interleave (toStream m1) (toStream m2)
878-- | Parallel interleaved composition, in contrast to '<|>' this operator
879-- "merges" streams in a left biased manner rather than fairly interleaving
880-- them. It keeps yielding from the stream on the left as long as it can. If
881-- the left stream blocks or cannot keep up with the pace of the consumer it
882-- can yield from the stream on the right in parallel. Unlike '<|>' it can be
883-- used to fold infinite containers of streams.
884{-# INLINE (<|) #-}
885(<|) :: (Streaming t, MonadAsync m) => t m a -> t m a -> t m a
886m1 <| m2 = fromStream $ parLeft (toStream m1) (toStream m2)
888------------------------------------------------------------------------------
889-- Fold Utilities
890------------------------------------------------------------------------------
892-- $foldutils
893-- These utilities are designed to pass the first argument as one of the sum
894-- style composition operators (i.e. '<>', '<=>', '<|', '<|>') to conveniently
895-- fold a container using any style of stream composition.
897-- | Like the 'Prelude' 'fold' but allows you to specify a binary sum style
898-- stream composition operator to fold a container of streams.
899--
900-- @foldWith (<>) $ map return [1..3]@
901{-# INLINABLE foldWith #-}
902foldWith :: (Streaming t, Foldable f)
903 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
904foldWith f = foldr f nil
906-- | Like 'foldMap' but allows you to specify a binary sum style composition
907-- operator to fold a container of streams. Maps a monadic streaming action on
908-- the container before folding it.
909--
910-- @foldMapWith (<>) return [1..3]@
911{-# INLINABLE foldMapWith #-}
912foldMapWith :: (Streaming t, Foldable f)
913 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
914foldMapWith f g = foldr (f . g) nil
916-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
917-- monadic streaming function is the last argument.
918{-# INLINABLE forEachWith #-}
919forEachWith :: (Streaming t, Foldable f)
920 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
921forEachWith f xs g = foldr (f . g) nil xs