on 328365e help sign in
streamly/src/Streamly/Streams.hs
1490 lines 49 kB history raw
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving#-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE StandaloneDeriving #-}
10{-# LANGUAGE UndecidableInstances #-} -- XXX
12-- |
13-- Module : Streamly.Streams
14-- Copyright : (c) 2017 Harendra Kumar
15--
16-- License : BSD3
17-- Maintainer : harendra.kumar@gmail.com
18-- Stability : experimental
19-- Portability : GHC
20--
21--
22module Streamly.Streams
23 (
24 IsStream (..)
25 , Streaming -- deprecated
26 , S.MonadAsync
28 -- * Construction
29 , nil
30 , cons
31 , (.:)
32 , streamBuild
33 , fromCallback
34 , fromSVar
36 -- * Elimination
37 , streamFold
38 , runStream
39 , runStreaming -- deprecated
40 , toSVar
42 -- * Transformation
43 , mkAsync
44 , (|$)
45 , (|&)
46 , (|$.)
47 , (|&.)
49 -- * Merging Streams
50 , serial
51 , wSerial
52 , ahead
53 , async
54 , wAsync
55 , parallel
56 , (<=>) --deprecated
57 , (<|) --deprecated
59 -- * IO Streams
60 , Serial
61 , WSerial
62 , Ahead
63 , Async
64 , WAsync
65 , Parallel
66 , ZipSerial
67 , ZipAsync
69 -- * Stream Transformers
70 , SerialT
71 , StreamT -- deprecated
72 , WSerialT
73 , InterleavedT -- deprecated
74 , AheadT
75 , AsyncT
76 , WAsyncT
77 , ParallelT
78 , ZipStream -- deprecated
79 , ZipSerialM
80 , ZipAsyncM
82 -- * Type Adapters
83 , serially -- deprecated
84 , wSerially
85 , interleaving -- deprecated
86 , aheadly
87 , asyncly
88 , wAsyncly
89 , parallely
90 , zipSerially
91 , zipping -- deprecated
92 , zipAsyncly
93 , zippingAsync -- deprecated
94 , adapt
96 -- * Running Streams
97 , runStreamT -- deprecated
98 , runInterleavedT -- deprecated
99 , runAsyncT -- deprecated
100 , runParallelT -- deprecated
101 , runZipStream -- deprecated
102 , runZipAsync -- deprecated
104 -- * Fold Utilities
105 , foldWith
106 , foldMapWith
107 , forEachWith
108 )
109where
111import Control.Monad (ap)
112import Control.Monad.Base (MonadBase (..), liftBaseDefault)
113import Control.Monad.Catch (MonadThrow, throwM)
114-- import Control.Monad.Error.Class (MonadError(..))
115import Control.Monad.IO.Class (MonadIO(..))
116import Control.Monad.Reader.Class (MonadReader(..))
117import Control.Monad.State.Class (MonadState(..))
118import Control.Monad.Trans.Class (MonadTrans (lift))
119import Data.Semigroup (Semigroup(..))
120import Streamly.Core ( MonadAsync , SVar,
121 SVarStyle(..))
122import qualified Streamly.Core as S
124------------------------------------------------------------------------------
125-- Types that can behave as a Stream
126------------------------------------------------------------------------------
128infixr 5 `consM`
129infixr 5 |:
131-- | Class of types that can represent a stream of elements of some type 'a' in
132-- some monad 'm'.
133--
134-- @since 0.2.0
135class IsStream t where
136 toStream :: t m a -> S.Stream m a
137 fromStream :: S.Stream m a -> t m a
138 -- | Constructs a stream by adding a monadic action at the head of an
139 -- existing stream. For example:
140 --
141 -- @
142 -- > toList $ getLine \`consM` getLine \`consM` nil
143 -- hello
144 -- world
145 -- ["hello","world"]
146 -- @
147 --
148 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
149 --
150 -- @since 0.2.0
151 consM :: MonadAsync m => m a -> t m a -> t m a
152 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
153 -- to remember that @|@ comes before ':'.
154 --
155 -- @
156 -- > toList $ getLine |: getLine |: nil
157 -- hello
158 -- world
159 -- ["hello","world"]
160 -- @
161 --
162 -- @
163 -- let delay = threadDelay 1000000 >> print 1
164 -- runStream $ serially $ delay |: delay |: delay |: nil
165 -- runStream $ parallely $ delay |: delay |: delay |: nil
166 -- @
167 --
168 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
169 --
170 -- @since 0.2.0
171 (|:) :: MonadAsync m => m a -> t m a -> t m a
172 -- We can define (|:) just as 'consM' but it is defined explicitly for each
173 -- type because we want to use SPECIALIZE pragma on the definition.
175-- | Same as 'IsStream'.
176--
177-- @since 0.1.0
178{-# DEPRECATED Streaming "Please use IsStream instead." #-}
179type Streaming = IsStream
181------------------------------------------------------------------------------
182-- Constructing a stream
183------------------------------------------------------------------------------
185-- | An empty stream.
186--
187-- @
188-- > toList nil
189-- []
190-- @
191--
192-- @since 0.1.0
193nil :: IsStream t => t m a
194nil = fromStream S.nil
196-- | Constructs a stream by adding a monadic action at the head of an existing
197-- stream. For example:
198--
199-- @
200-- > toList $ getLine \`consM` getLine \`consM` nil
201-- hello
202-- world
203-- ["hello","world"]
204-- @
205--
206-- @since 0.2.0
207consMSerial :: (IsStream t, Monad m) => m a -> t m a -> t m a
208consMSerial m r = fromStream $ S.consM m (toStream r)
210infixr 5 `cons`
212-- | Construct a stream by adding a pure value at the head of an existing
213-- stream. For pure values it can be faster than 'consM'. For example:
214--
215-- @
216-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
217-- [1,2,3]
218-- @
219--
220-- @since 0.1.0
221cons :: IsStream t => a -> t m a -> t m a
222cons a r = fromStream $ S.cons a (toStream r)
224infixr 5 .:
226-- | Operator equivalent of 'cons'.
227--
228-- @
229-- > toList $ 1 .: 2 .: 3 .: nil
230-- [1,2,3]
231-- @
232--
233-- @since 0.1.1
234(.:) :: IsStream t => a -> t m a -> t m a
235(.:) = cons
237-- | Build a stream from its church encoding. The function passed maps
238-- directly to the underlying representation of the stream type. The second
239-- parameter to the function is the "yield" function yielding a value and the
240-- remaining stream if any otherwise 'Nothing'. The third parameter is to
241-- represent an "empty" stream.
242streamBuild :: IsStream t
243 => (forall r. Maybe (SVar m a)
244 -> (a -> t m a -> m r)
245 -> (a -> m r)
246 -> m r
247 -> m r)
248 -> t m a
249streamBuild k = fromStream $ S.Stream $ \svr stp sng yld ->
250 let yield a r = yld a (toStream r)
251 in k svr yield sng stp
253-- | Build a singleton stream from a callback function.
254fromCallback :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
255fromCallback k = fromStream $ S.Stream $ \_ _ sng _ -> k sng
257-- | Read an SVar to get a stream.
258fromSVar :: (MonadAsync m, IsStream t) => SVar m a -> t m a
259fromSVar sv = fromStream $ S.fromStreamVar sv
261------------------------------------------------------------------------------
262-- Destroying a stream
263------------------------------------------------------------------------------
265-- | Fold a stream using its church encoding. The second argument is the "step"
266-- function consuming an element and the remaining stream, if any. The third
267-- argument is for consuming an "empty" stream that yields nothing.
268streamFold
269 :: IsStream t
270 => Maybe (SVar m a)
271 -> (a -> t m a -> m r)
272 -> (a -> m r)
273 -> m r
274 -> t m a
275 -> m r
276streamFold svr step single blank m =
277 let yield a x = step a (fromStream x)
278 in (S.runStream (toStream m)) svr blank single yield
280-- | Run a streaming composition, discard the results. By default it interprets
281-- the stream as 'SerialT', to run other types of streams use the type adapting
282-- combinators for example @runStream . 'asyncly'@.
283--
284-- @since 0.2.0
285runStream :: Monad m => SerialT m a -> m ()
286runStream m = go (toStream m)
287 where
288 go m1 =
289 let stop = return ()
290 single _ = return ()
291 yield _ r = go r
292 in (S.runStream m1) Nothing stop single yield
294-- | Same as 'runStream'
295--
296-- @since 0.1.0
297{-# DEPRECATED runStreaming "Please use runStream instead." #-}
298runStreaming :: (Monad m, IsStream t) => t m a -> m ()
299runStreaming = runStream . adapt
301-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
302-- be read back from the SVar using 'fromSVar'.
303toSVar :: (IsStream t, MonadAsync m) => SVar m a -> t m a -> m ()
304toSVar sv m = S.toStreamVar sv (toStream m)
306------------------------------------------------------------------------------
307-- Transformation
308------------------------------------------------------------------------------
310-- XXX Get rid of this?
311-- | Make a stream asynchronous, triggers the computation and returns a stream
312-- in the underlying monad representing the output generated by the original
313-- computation. The returned action is exhaustible and must be drained once. If
314-- not drained fully we may have a thread blocked forever and once exhausted it
315-- will always return 'empty'.
316--
317-- @since 0.2.0
318mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
319mkAsync m = do
320 sv <- S.newStreamVar1 AsyncVar (toStream m)
321 return $ fromSVar sv
323{-# INLINE applyWith #-}
324applyWith :: (IsStream t, MonadAsync m)
325 => SVarStyle -> (t m a -> t m b) -> t m a -> t m b
326applyWith style f x = fromStream $
327 S.applyWith style (toStream . f . fromStream) (toStream x)
329{-# INLINE runWith #-}
330runWith :: (IsStream t, MonadAsync m)
331 => SVarStyle -> (t m a -> m b) -> t m a -> m b
332runWith style f x = S.runWith style (f . fromStream) (toStream x)
334infixr 0 |$
335infixr 0 |$.
337infixl 1 |&
338infixl 1 |&.
340-- | Parallel function application operator for streams; just like the regular
341-- function application operator '$' except that it is concurrent. The
342-- following code prints a value every second even though each stage adds a 1
343-- second delay.
344--
345--
346-- @
347-- runStream $
348-- S.mapM (\\x -> threadDelay 1000000 >> print x)
349-- |$ S.repeatM (threadDelay 1000000 >> return 1)
350-- @
351--
352-- /Concurrent/
353--
354-- @since 0.3.0
355{-# INLINE (|$) #-}
356(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b
357f |$ x = applyWith ParallelVar f x
359-- | Parallel reverse function application operator for streams; just like the
360-- regular reverse function application operator '&' except that it is
361-- concurrent.
362--
363-- @
364-- runStream $
365-- S.repeatM (threadDelay 1000000 >> return 1)
366-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
367-- @
368--
369-- /Concurrent/
370--
371-- @since 0.3.0
372{-# INLINE (|&) #-}
373(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
374x |& f = f |$ x
376-- | Parallel function application operator; applies a @run@ or @fold@ function
377-- to a stream such that the fold consumer and the stream producer run in
378-- parallel. A @run@ or @fold@ function reduces the stream to a value in the
379-- underlying monad. The @.@ at the end of the operator is a mnemonic for
380-- termination of the stream.
381--
382-- @
383-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
384-- |$. S.repeatM (threadDelay 1000000 >> return 1)
385-- @
386--
387-- /Concurrent/
388--
389-- @since 0.3.0
390{-# INLINE (|$.) #-}
391(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b
392f |$. x = runWith ParallelVar f x
394-- | Parallel reverse function application operator for applying a run or fold
395-- functions to a stream. Just like '|$.' except that the operands are reversed.
396--
397-- @
398-- S.repeatM (threadDelay 1000000 >> return 1)
399-- |&. S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
400-- @
401--
402-- /Concurrent/
403--
404-- @since 0.3.0
405{-# INLINE (|&.) #-}
406(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
407x |&. f = f |$. x
409------------------------------------------------------------------------------
410-- CPP macros for common instances
411------------------------------------------------------------------------------
413-- XXX use template haskell instead and include Monoid and IsStream instances
414-- as well.
416withLocal :: MonadReader r m => (r -> r) -> S.Stream m a -> S.Stream m a
417withLocal f m =
418 S.Stream $ \_ stp sng yld ->
419 let single = local f . sng
420 yield a r = local f $ yld a (withLocal f r)
421 in (S.runStream m) Nothing (local f stp) single yield
423{-
424-- XXX handle and test cross thread state transfer
425withCatchError
426 :: MonadError e m
427 => S.Stream m a -> (e -> S.Stream m a) -> S.Stream m a
428withCatchError m h =
429 S.Stream $ \_ stp sng yld ->
430 let run x = S.runStream x Nothing stp sng yield
431 handle r = r `catchError` \e -> run $ h e
432 yield a r = yld a (withCatchError r h)
433 in handle $ run m
434-}
436#define MONADPARALLEL , MonadAsync m
438#define MONAD_APPLICATIVE_INSTANCE(STREAM,CONSTRAINT) \
439instance (Monad m CONSTRAINT) => Applicative (STREAM m) where { \
440 pure = STREAM . S.singleton; \
441 (<*>) = ap }
443#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
444instance (MonadBase b m, Monad m CONSTRAINT) => MonadBase b (STREAM m) where {\
445 liftBase = liftBaseDefault }; \
446 \
447instance (MonadIO m CONSTRAINT) => MonadIO (STREAM m) where { \
448 liftIO = lift . liftIO }; \
449 \
450instance (MonadThrow m CONSTRAINT) => MonadThrow (STREAM m) where { \
451 throwM = lift . throwM }; \
452 \
453{- \
454instance (MonadError e m CONSTRAINT) => MonadError e (STREAM m) where { \
455 throwError = lift . throwError; \
456 catchError m h = \
457 fromStream $ withCatchError (toStream m) (\e -> toStream $ h e) }; \
458-} \
459 \
460instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
461 ask = lift ask; \
462 local f m = fromStream $ withLocal f (toStream m) }; \
463 \
464instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
465 get = lift get; \
466 put x = lift (put x); \
467 state k = lift (state k) }
469------------------------------------------------------------------------------
470-- SerialT
471------------------------------------------------------------------------------
473-- | Deep serial composition or serial composition with depth first traversal.
474-- The 'Semigroup' instance of 'SerialT' appends two streams serially in a
475-- depth first manner, yielding all elements from the first stream, and then
476-- all elements from the second stream.
477--
478-- @
479-- import Streamly
480-- import qualified "Streamly.Prelude" as S
481--
482-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
483-- @
484-- @
485-- [1,2,3,4]
486-- @
487--
488-- The 'Monad' instance runs the /monadic continuation/ for each
489-- element of the stream, serially.
490--
491-- @
492-- main = 'runStream' . 'serially' $ do
493-- x <- return 1 \<\> return 2
494-- S.once $ print x
495-- @
496-- @
497-- 1
498-- 2
499-- @
500--
501-- 'SerialT' nests streams serially in a depth first manner.
502--
503-- @
504-- main = 'runStream' . 'serially' $ do
505-- x <- return 1 \<\> return 2
506-- y <- return 3 \<\> return 4
507-- S.once $ print (x, y)
508-- @
509-- @
510-- (1,3)
511-- (1,4)
512-- (2,3)
513-- (2,4)
514-- @
515--
516-- This behavior of 'SerialT' is exactly like a list transformer. We call the
517-- monadic code being run for each element of the stream a monadic
518-- continuation. In imperative paradigm we can think of this composition as
519-- nested @for@ loops and the monadic continuation is the body of the loop. The
520-- loop iterates for all elements of the stream.
521--
522-- The 'serially' combinator can be omitted as the default stream type is
523-- 'SerialT'.
524-- Note that serial composition with depth first traversal can be used to
525-- combine an infinite number of streams as it explores only one stream at a
526-- time.
527--
528-- @since 0.2.0
529newtype SerialT m a = SerialT {getSerialT :: S.Stream m a}
530 deriving (Semigroup, Monoid, Functor, MonadTrans)
532-- |
533-- @since 0.1.0
534{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
535type StreamT = SerialT
537instance IsStream SerialT where
538 toStream = getSerialT
539 fromStream = SerialT
541 {-# INLINE consM #-}
542 {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
543 consM :: Monad m => m a -> SerialT m a -> SerialT m a
544 consM = consMSerial
546 {-# INLINE (|:) #-}
547 {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
548 (|:) :: Monad m => m a -> SerialT m a -> SerialT m a
549 (|:) = consMSerial
551------------------------------------------------------------------------------
552-- Semigroup
553------------------------------------------------------------------------------
555-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
556-- Appends two streams sequentially, yielding all elements from the first
557-- stream, and then all elements from the second stream.
558--
559-- @since 0.2.0
560{-# INLINE serial #-}
561serial :: IsStream t => t m a -> t m a -> t m a
562serial m1 m2 = fromStream $ S.serial (toStream m1) (toStream m2)
564------------------------------------------------------------------------------
565-- Monad
566------------------------------------------------------------------------------
568instance Monad m => Monad (SerialT m) where
569 return = pure
570 (SerialT (S.Stream m)) >>= f = SerialT $ S.Stream $ \_ stp sng yld ->
571 let run x = (S.runStream x) Nothing stp sng yld
572 single a = run $ toStream (f a)
573 yield a r = run $ toStream $ f a <> (fromStream r >>= f)
574 in m Nothing stp single yield
576------------------------------------------------------------------------------
577-- Other instances
578------------------------------------------------------------------------------
580MONAD_APPLICATIVE_INSTANCE(SerialT,)
581MONAD_COMMON_INSTANCES(SerialT,)
583------------------------------------------------------------------------------
584-- WSerialT
585------------------------------------------------------------------------------
587-- | Wide serial composition or serial composition with a breadth first
588-- traversal. The 'Semigroup' instance of 'WSerialT' traverses
589-- the two streams in a breadth first manner. In other words, it interleaves
590-- two streams, yielding one element from each stream alternately.
591--
592-- @
593-- import Streamly
594-- import qualified "Streamly.Prelude" as S
595--
596-- main = ('toList' . 'wSerially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
597-- @
598-- @
599-- [1,3,2,4]
600-- @
601--
602-- Similarly, the 'Monad' instance interleaves the iterations of the
603-- inner and the outer loop, nesting loops in a breadth first manner.
604--
605--
606-- @
607-- main = 'runStream' . 'wSerially' $ do
608-- x <- return 1 \<\> return 2
609-- y <- return 3 \<\> return 4
610-- S.once $ print (x, y)
611-- @
612-- @
613-- (1,3)
614-- (2,3)
615-- (1,4)
616-- (2,4)
617-- @
618--
619-- Note that a serial composition with breadth first traversal can only combine
620-- a finite number of streams as it needs to retain state for each unfinished
621-- stream.
622--
623-- @since 0.2.0
624newtype WSerialT m a = WSerialT {getWSerialT :: S.Stream m a}
625 deriving (Functor, MonadTrans)
627-- |
628-- @since 0.1.0
629{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
630type InterleavedT = WSerialT
632instance IsStream WSerialT where
633 toStream = getWSerialT
634 fromStream = WSerialT
636 {-# INLINE consM #-}
637 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
638 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
639 consM = consMSerial
641 {-# INLINE (|:) #-}
642 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
643 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
644 (|:) = consMSerial
646------------------------------------------------------------------------------
647-- Semigroup
648------------------------------------------------------------------------------
650-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
651-- Interleaves two streams, yielding one element from each stream alternately.
652--
653-- @since 0.2.0
654{-# INLINE wSerial #-}
655wSerial :: IsStream t => t m a -> t m a -> t m a
656wSerial m1 m2 = fromStream $ S.wSerial (toStream m1) (toStream m2)
658instance Semigroup (WSerialT m a) where
659 (<>) = wSerial
661infixr 5 <=>
663-- | Same as 'wSerial'.
664--
665-- @since 0.1.0
666{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
667{-# INLINE (<=>) #-}
668(<=>) :: IsStream t => t m a -> t m a -> t m a
669(<=>) = wSerial
671------------------------------------------------------------------------------
672-- Monoid
673------------------------------------------------------------------------------
675instance Monoid (WSerialT m a) where
676 mempty = nil
677 mappend = (<>)
679------------------------------------------------------------------------------
680-- Monad
681------------------------------------------------------------------------------
683instance Monad m => Monad (WSerialT m) where
684 return = pure
685 (WSerialT (S.Stream m)) >>= f = WSerialT $ S.Stream $ \_ stp sng yld ->
686 let run x = (S.runStream x) Nothing stp sng yld
687 single a = run $ toStream (f a)
688 yield a r = run $ toStream $ f a <> (fromStream r >>= f)
689 in m Nothing stp single yield
691------------------------------------------------------------------------------
692-- Other instances
693------------------------------------------------------------------------------
695MONAD_APPLICATIVE_INSTANCE(WSerialT,)
696MONAD_COMMON_INSTANCES(WSerialT,)
698------------------------------------------------------------------------------
699-- AheadT
700------------------------------------------------------------------------------
702-- | Deep ahead composition or ahead composition with depth first traversal.
703-- The semigroup composition of 'AheadT' appends streams in a depth first
704-- manner just like 'SerialT' except that it can produce elements concurrently
705-- ahead of time. It is like 'AsyncT' except that 'AsyncT' produces the output
706-- as it arrives whereas 'AheadT' orders the output in the traversal order.
707--
708-- @
709-- main = ('toList' . 'aheadly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
710-- @
711-- @
712-- [1,2,3,4]
713-- @
714--
715-- Any exceptions generated by a constituent stream are propagated to the
716-- output stream.
717--
718-- Similarly, the monad instance of 'AheadT' may run each iteration
719-- concurrently ahead of time but presents the results in the same order as
720-- 'SerialT'.
721--
722-- @
723-- import "Streamly"
724-- import qualified "Streamly.Prelude" as S
725-- import Control.Concurrent
726--
727-- main = 'runStream' . 'aheadly' $ do
728-- n <- return 3 \<\> return 2 \<\> return 1
729-- S.once $ do
730-- threadDelay (n * 1000000)
731-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
732-- @
733-- @
734-- ThreadId 40: Delay 1
735-- ThreadId 39: Delay 2
736-- ThreadId 38: Delay 3
737-- @
738--
739-- All iterations may run in the same thread if they do not block.
740--
741-- Note that ahead composition with depth first traversal can be used to
742-- combine infinite number of streams as it explores only a bounded number of
743-- streams at a time.
744--
745-- @since 0.3.0
746newtype AheadT m a = AheadT {getAheadT :: S.Stream m a}
747 deriving (Functor, MonadTrans)
749instance IsStream AheadT where
750 toStream = getAheadT
751 fromStream = AheadT
753 {-# INLINE consM #-}
754 {-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
755 consM m r = fromStream $ S.consMAhead m (toStream r)
757 {-# INLINE (|:) #-}
758 {-# SPECIALIZE (|:) :: IO a -> AheadT IO a -> AheadT IO a #-}
759 (|:) = consM
761------------------------------------------------------------------------------
762-- Semigroup
763------------------------------------------------------------------------------
765-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
766-- Merges two streams sequentially but with concurrent lookahead.
767--
768-- @since 0.3.0
769{-# INLINE ahead #-}
770ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
771ahead m1 m2 = fromStream $ S.ahead (toStream m1) (toStream m2)
773instance MonadAsync m => Semigroup (AheadT m a) where
774 (<>) = ahead
776------------------------------------------------------------------------------
777-- Monoid
778------------------------------------------------------------------------------
780instance MonadAsync m => Monoid (AheadT m a) where
781 mempty = nil
782 mappend = (<>)
784------------------------------------------------------------------------------
785-- Monad
786------------------------------------------------------------------------------
788{-# INLINE aheadbind #-}
789aheadbind
790 :: MonadAsync m
791 => S.Stream m a
792 -> (a -> S.Stream m b)
793 -> S.Stream m b
794aheadbind m f = go m
795 where
796 go (S.Stream g) =
797 S.Stream $ \ctx stp sng yld ->
798 let run x = (S.runStream x) ctx stp sng yld
799 single a = run $ f a
800 yield a r = run $ f a `S.ahead` go r
801 in g Nothing stp single yield
803instance MonadAsync m => Monad (AheadT m) where
804 return = pure
805 (AheadT m) >>= f = AheadT $ aheadbind m (getAheadT . f)
807------------------------------------------------------------------------------
808-- Other instances
809------------------------------------------------------------------------------
811MONAD_APPLICATIVE_INSTANCE(AheadT,MONADPARALLEL)
812MONAD_COMMON_INSTANCES(AheadT, MONADPARALLEL)
814------------------------------------------------------------------------------
815-- AsyncT
816------------------------------------------------------------------------------
818-- | Deep async composition or async composition with depth first traversal. In
819-- a left to right 'Semigroup' composition it tries to yield elements from the
820-- left stream as long as it can, but it can run the right stream in parallel
821-- if it needs to, based on demand. The right stream can be run if the left
822-- stream blocks on IO or cannot produce elements fast enough for the consumer.
823--
824-- @
825-- main = ('toList' . 'asyncly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
826-- @
827-- @
828-- [1,2,3,4]
829-- @
830--
831-- Any exceptions generated by a constituent stream are propagated to the
832-- output stream. The output and exceptions from a single stream are guaranteed
833-- to arrive in the same order in the resulting stream as they were generated
834-- in the input stream. However, the relative ordering of elements from
835-- different streams in the resulting stream can vary depending on scheduling
836-- and generation delays.
837--
838-- Similarly, the monad instance of 'AsyncT' /may/ run each iteration
839-- concurrently based on demand. More concurrent iterations are started only
840-- if the previous iterations are not able to produce enough output for the
841-- consumer.
842--
843-- @
844-- import "Streamly"
845-- import qualified "Streamly.Prelude" as S
846-- import Control.Concurrent
847--
848-- main = 'runStream' . 'asyncly' $ do
849-- n <- return 3 \<\> return 2 \<\> return 1
850-- S.once $ do
851-- threadDelay (n * 1000000)
852-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
853-- @
854-- @
855-- ThreadId 40: Delay 1
856-- ThreadId 39: Delay 2
857-- ThreadId 38: Delay 3
858-- @
859--
860-- All iterations may run in the same thread if they do not block.
861--
862-- Note that async composition with depth first traversal can be used to
863-- combine infinite number of streams as it explores only a bounded number of
864-- streams at a time.
865--
866-- @since 0.1.0
867newtype AsyncT m a = AsyncT {getAsyncT :: S.Stream m a}
868 deriving (Functor, MonadTrans)
870instance IsStream AsyncT where
871 toStream = getAsyncT
872 fromStream = AsyncT
874 {-# INLINE consM #-}
875 {-# SPECIALIZE consM :: IO a -> AsyncT IO a -> AsyncT IO a #-}
876 consM m r = fromStream $ S.consMAsync m (toStream r)
878 {-# INLINE (|:) #-}
879 {-# SPECIALIZE (|:) :: IO a -> AsyncT IO a -> AsyncT IO a #-}
880 (|:) = consM
882------------------------------------------------------------------------------
883-- Semigroup
884------------------------------------------------------------------------------
886-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
887-- Merges two streams possibly concurrently, preferring the
888-- elements from the left one when available.
889--
890-- @since 0.2.0
891{-# INLINE async #-}
892async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
893async m1 m2 = fromStream $ S.async (toStream m1) (toStream m2)
895-- | Same as 'async'.
896--
897-- @since 0.1.0
898{-# DEPRECATED (<|) "Please use 'async' instead." #-}
899{-# INLINE (<|) #-}
900(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
901(<|) = async
903instance MonadAsync m => Semigroup (AsyncT m a) where
904 (<>) = async
906------------------------------------------------------------------------------
907-- Monoid
908------------------------------------------------------------------------------
910instance MonadAsync m => Monoid (AsyncT m a) where
911 mempty = nil
912 mappend = (<>)
914------------------------------------------------------------------------------
915-- Monad
916------------------------------------------------------------------------------
918{-# INLINE parbind #-}
919parbind
920 :: (forall c. S.Stream m c -> S.Stream m c -> S.Stream m c)
921 -> S.Stream m a
922 -> (a -> S.Stream m b)
923 -> S.Stream m b
924parbind par m f = go m
925 where
926 go (S.Stream g) =
927 S.Stream $ \ctx stp sng yld ->
928 let run x = (S.runStream x) ctx stp sng yld
929 single a = run $ f a
930 yield a r = run $ f a `par` go r
931 in g Nothing stp single yield
933instance MonadAsync m => Monad (AsyncT m) where
934 return = pure
935 (AsyncT m) >>= f = AsyncT $ parbind S.async m (getAsyncT . f)
937------------------------------------------------------------------------------
938-- Other instances
939------------------------------------------------------------------------------
941MONAD_APPLICATIVE_INSTANCE(AsyncT,MONADPARALLEL)
942MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
944------------------------------------------------------------------------------
945-- WAsyncT
946------------------------------------------------------------------------------
948-- | Wide async composition or async composition with breadth first traversal.
949-- The Semigroup instance of 'WAsyncT' concurrently /traverses/ the composed
950-- streams using a depth first travesal or in a round robin fashion, yielding
951-- elements from both streams alternately.
952--
953-- @
954-- main = ('toList' . 'wAsyncly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
955-- @
956-- @
957-- [1,3,2,4]
958-- @
959--
960-- Any exceptions generated by a constituent stream are propagated to the
961-- output stream. The output and exceptions from a single stream are guaranteed
962-- to arrive in the same order in the resulting stream as they were generated
963-- in the input stream. However, the relative ordering of elements from
964-- different streams in the resulting stream can vary depending on scheduling
965-- and generation delays.
966--
967-- Similarly, the 'Monad' instance of 'WAsyncT' runs /all/ iterations fairly
968-- concurrently using a round robin scheduling.
969--
970-- @
971-- import "Streamly"
972-- import qualified "Streamly.Prelude" as S
973-- import Control.Concurrent
974--
975-- main = 'runStream' . 'wAsyncly' $ do
976-- n <- return 3 \<\> return 2 \<\> return 1
977-- S.once $ do
978-- threadDelay (n * 1000000)
979-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
980-- @
981-- @
982-- ThreadId 40: Delay 1
983-- ThreadId 39: Delay 2
984-- ThreadId 38: Delay 3
985-- @
986--
987-- Unlike 'AsyncT' all iterations are guaranteed to run fairly
988-- concurrently, unconditionally.
989--
990-- Note that async composition with breadth first traversal can only combine a
991-- finite number of streams as it needs to retain state for each unfinished
992-- stream.
993--
994-- @since 0.2.0
995newtype WAsyncT m a = WAsyncT {getWAsyncT :: S.Stream m a}
996 deriving (Functor, MonadTrans)
998instance IsStream WAsyncT where
999 toStream = getWAsyncT
1000 fromStream = WAsyncT
1002 {-# INLINE consM #-}
1003 {-# SPECIALIZE consM :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
1004 consM m r = fromStream $ S.consMWAsync m (toStream r)
1006 {-# INLINE (|:) #-}
1007 {-# SPECIALIZE (|:) :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
1008 (|:) = consM
1010------------------------------------------------------------------------------
1011-- Semigroup
1012------------------------------------------------------------------------------
1014-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
1015-- Merges two streams concurrently choosing elements from both fairly.
1017-- @since 0.2.0
1018{-# INLINE wAsync #-}
1019wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
1020wAsync m1 m2 = fromStream $ S.wAsync (toStream m1) (toStream m2)
1022instance MonadAsync m => Semigroup (WAsyncT m a) where
1023 (<>) = wAsync
1025------------------------------------------------------------------------------
1026-- Monoid
1027------------------------------------------------------------------------------
1029instance MonadAsync m => Monoid (WAsyncT m a) where
1030 mempty = nil
1031 mappend = (<>)
1033------------------------------------------------------------------------------
1034-- Monad
1035------------------------------------------------------------------------------
1037instance MonadAsync m => Monad (WAsyncT m) where
1038 return = pure
1039 (WAsyncT m) >>= f =
1040 WAsyncT $ parbind S.wAsync m (getWAsyncT . f)
1042------------------------------------------------------------------------------
1043-- Other instances
1044------------------------------------------------------------------------------
1046MONAD_APPLICATIVE_INSTANCE(WAsyncT,MONADPARALLEL)
1047MONAD_COMMON_INSTANCES(WAsyncT, MONADPARALLEL)
1049------------------------------------------------------------------------------
1050-- ParallelT
1051------------------------------------------------------------------------------
1053-- | Async composition with simultaneous traversal of all streams.
1055-- The Semigroup instance of 'ParallelT' concurrently /merges/ two streams,
1056-- running both strictly concurrently and yielding elements from both streams
1057-- as they arrive. When multiple streams are combined using 'ParallelT' each
1058-- one is evaluated in its own thread and the results produced are presented in
1059-- the combined stream on a first come first serve basis.
1061-- 'AsyncT' and 'WAsyncT' are /concurrent lookahead streams/ each with a
1062-- specific type of consumption pattern (depth first or breadth first). Since
1063-- they are lookahead, they may introduce certain default latency in starting
1064-- more concurrent tasks for efficiency reasons or may put a default limitation
1065-- on the resource consumption (e.g. number of concurrent threads for
1066-- lookahead). If we look at the implementation detail, they both can share a
1067-- pool of worker threads to evaluate the streams in the desired pattern and at
1068-- the desired rate. However, 'ParallelT' uses a separate runtime thread to
1069-- evaluate each stream.
1071-- 'WAsyncT' is similar to 'ParallelT', as both of them evaluate the
1072-- constituent streams fairly in a round robin fashion.
1073-- However, the key difference is that 'WAsyncT' is lazy or pull driven
1074-- whereas 'ParallelT' is strict or push driven. 'ParallelT' immediately
1075-- starts concurrent evaluation of both the streams (in separate threads) and
1076-- later picks the results whereas 'WAsyncT' may wait for a certain latency
1077-- threshold before initiating concurrent evaluation of the next stream. The
1078-- concurrent scheduling of the next stream or the degree of concurrency is
1079-- driven by the feedback from the consumer. In case of 'ParallelT' each stream
1080-- is evaluated in a separate thread and results are /pushed/ to a shared
1081-- output buffer, the evaluation rate is controlled by blocking when the buffer
1082-- is full.
1084-- Concurrent lookahead streams are generally more efficient than
1085-- 'ParallelT' and can work pretty efficiently even for smaller tasks because
1086-- they do not necessarily use a separate thread for each task. So they should
1087-- be preferred over 'ParallelT' especially when efficiency is a concern and
1088-- simultaneous strict evaluation is not a requirement. 'ParallelT' is useful
1089-- for cases when the streams are required to be evaluated simultaneously
1090-- irrespective of how the consumer consumes them e.g. when we want to race
1091-- two tasks and want to start both strictly at the same time or if we have
1092-- timers in the parallel tasks and our results depend on the timers being
1093-- started at the same time. We can say that 'ParallelT' is almost the same
1094-- (modulo some implementation differences) as 'WAsyncT' when the latter is
1095-- used with unlimited lookahead and zero latency in initiating lookahead.
1097-- @
1098-- main = ('toList' . 'parallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
1099-- @
1100-- @
1101-- [1,3,2,4]
1102-- @
1104-- When streams with more than one element are merged, it yields whichever
1105-- stream yields first without any bias, unlike the 'Async' style streams.
1107-- Any exceptions generated by a constituent stream are propagated to the
1108-- output stream. The output and exceptions from a single stream are guaranteed
1109-- to arrive in the same order in the resulting stream as they were generated
1110-- in the input stream. However, the relative ordering of elements from
1111-- different streams in the resulting stream can vary depending on scheduling
1112-- and generation delays.
1114-- Similarly, the 'Monad' instance of 'ParallelT' runs /all/ iterations
1115-- of the loop concurrently.
1117-- @
1118-- import "Streamly"
1119-- import qualified "Streamly.Prelude" as S
1120-- import Control.Concurrent
1122-- main = 'runStream' . 'parallely' $ do
1123-- n <- return 3 \<\> return 2 \<\> return 1
1124-- S.once $ do
1125-- threadDelay (n * 1000000)
1126-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
1127-- @
1128-- @
1129-- ThreadId 40: Delay 1
1130-- ThreadId 39: Delay 2
1131-- ThreadId 38: Delay 3
1132-- @
1134-- Note that parallel composition can only combine a finite number of
1135-- streams as it needs to retain state for each unfinished stream.
1137-- @since 0.1.0
1138newtype ParallelT m a = ParallelT {getParallelT :: S.Stream m a}
1139 deriving (Functor, MonadTrans)
1141instance IsStream ParallelT where
1142 toStream = getParallelT
1143 fromStream = ParallelT
1145 {-# INLINE consM #-}
1146 {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
1147 consM m r = fromStream $ S.consMParallel m (toStream r)
1149 {-# INLINE (|:) #-}
1150 {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
1151 (|:) = consM
1153------------------------------------------------------------------------------
1154-- Semigroup
1155------------------------------------------------------------------------------
1157-- | Polymorphic version of the 'Semigroup' operation '<>' of 'ParallelT'
1158-- Merges two streams concurrently.
1160-- @since 0.2.0
1161{-# INLINE parallel #-}
1162parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
1163parallel m1 m2 = fromStream $ S.parallel (toStream m1) (toStream m2)
1165instance MonadAsync m => Semigroup (ParallelT m a) where
1166 (<>) = parallel
1168------------------------------------------------------------------------------
1169-- Monoid
1170------------------------------------------------------------------------------
1172instance MonadAsync m => Monoid (ParallelT m a) where
1173 mempty = nil
1174 mappend = (<>)
1176------------------------------------------------------------------------------
1177-- Monad
1178------------------------------------------------------------------------------
1180instance MonadAsync m => Monad (ParallelT m) where
1181 return = pure
1182 (ParallelT m) >>= f = ParallelT $ parbind S.parallel m (getParallelT . f)
1184------------------------------------------------------------------------------
1185-- Other instances
1186------------------------------------------------------------------------------
1188MONAD_APPLICATIVE_INSTANCE(ParallelT,MONADPARALLEL)
1189MONAD_COMMON_INSTANCES(ParallelT, MONADPARALLEL)
1191------------------------------------------------------------------------------
1192-- Serially Zipping Streams
1193------------------------------------------------------------------------------
1195-- | The applicative instance of 'ZipSerialM' zips a number of streams serially
1196-- i.e. it produces one element from each stream serially and then zips all
1197-- those elements.
1199-- @
1200-- main = (toList . 'zipSerially' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
1201-- where s1 = fromFoldable [1, 2]
1202-- s2 = fromFoldable [3, 4]
1203-- s3 = fromFoldable [5, 6]
1204-- @
1205-- @
1206-- [(1,3,5),(2,4,6)]
1207-- @
1209-- The 'Semigroup' instance of this type works the same way as that of
1210-- 'SerialT'.
1212-- @since 0.2.0
1213newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: S.Stream m a}
1214 deriving (Functor, Semigroup, Monoid)
1216-- |
1217-- @since 0.1.0
1218{-# DEPRECATED ZipStream "Please use 'ZipSerialM' instead." #-}
1219type ZipStream = ZipSerialM
1221instance IsStream ZipSerialM where
1222 toStream = getZipSerialM
1223 fromStream = ZipSerialM
1225 {-# INLINE consM #-}
1226 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
1227 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
1228 consM = consMSerial
1230 {-# INLINE (|:) #-}
1231 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
1232 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
1233 (|:) = consMSerial
1235instance Monad m => Applicative (ZipSerialM m) where
1236 pure = ZipSerialM . S.repeat
1237 m1 <*> m2 = fromStream $ S.zipWith id (toStream m1) (toStream m2)
1239------------------------------------------------------------------------------
1240-- Parallely Zipping Streams
1241------------------------------------------------------------------------------
1243-- | Like 'ZipSerialM' but zips in parallel, it generates all the elements to
1244-- be zipped concurrently.
1246-- @
1247-- main = (toList . 'zipAsyncly' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
1248-- where s1 = fromFoldable [1, 2]
1249-- s2 = fromFoldable [3, 4]
1250-- s3 = fromFoldable [5, 6]
1251-- @
1252-- @
1253-- [(1,3,5),(2,4,6)]
1254-- @
1256-- The 'Semigroup' instance of this type works the same way as that of
1257-- 'SerialT'.
1259-- @since 0.2.0
1260newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: S.Stream m a}
1261 deriving (Functor, Semigroup, Monoid)
1263instance IsStream ZipAsyncM where
1264 toStream = getZipAsyncM
1265 fromStream = ZipAsyncM
1267 {-# INLINE consM #-}
1268 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
1269 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
1270 consM = consMSerial
1272 {-# INLINE (|:) #-}
1273 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
1274 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
1275 (|:) = consMSerial
1277instance MonadAsync m => Applicative (ZipAsyncM m) where
1278 pure = ZipAsyncM . S.repeat
1279 m1 <*> m2 = fromStream $ S.zipAsyncWith id (toStream m1) (toStream m2)
1281-------------------------------------------------------------------------------
1282-- Type adapting combinators
1283-------------------------------------------------------------------------------
1285-- | Adapt any specific stream type to any other specific stream type.
1287-- @since 0.1.0
1288adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
1289adapt = fromStream . toStream
1291-- | Fix the type of a polymorphic stream as 'SerialT'.
1293-- @since 0.1.0
1294serially :: IsStream t => SerialT m a -> t m a
1295serially = adapt
1297-- | Fix the type of a polymorphic stream as 'WSerialT'.
1299-- @since 0.2.0
1300wSerially :: IsStream t => WSerialT m a -> t m a
1301wSerially = adapt
1303-- | Same as 'wSerially'.
1305-- @since 0.1.0
1306{-# DEPRECATED interleaving "Please use wSerially instead." #-}
1307interleaving :: IsStream t => WSerialT m a -> t m a
1308interleaving = wSerially
1310-- | Fix the type of a polymorphic stream as 'AheadT'.
1312-- @since 0.3.0
1313aheadly :: IsStream t => AheadT m a -> t m a
1314aheadly = adapt
1316-- | Fix the type of a polymorphic stream as 'AsyncT'.
1318-- @since 0.1.0
1319asyncly :: IsStream t => AsyncT m a -> t m a
1320asyncly = adapt
1322-- | Fix the type of a polymorphic stream as 'WAsyncT'.
1324-- @since 0.2.0
1325wAsyncly :: IsStream t => WAsyncT m a -> t m a
1326wAsyncly = adapt
1328-- | Fix the type of a polymorphic stream as 'ParallelT'.
1330-- @since 0.1.0
1331parallely :: IsStream t => ParallelT m a -> t m a
1332parallely = adapt
1334-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
1336-- @since 0.2.0
1337zipSerially :: IsStream t => ZipSerialM m a -> t m a
1338zipSerially = adapt
1340-- | Same as 'zipSerially'.
1342-- @since 0.1.0
1343{-# DEPRECATED zipping "Please use zipSerially instead." #-}
1344zipping :: IsStream t => ZipSerialM m a -> t m a
1345zipping = zipSerially
1347-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
1349-- @since 0.2.0
1350zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
1351zipAsyncly = adapt
1353-- | Same as 'zipAsyncly'.
1355-- @since 0.1.0
1356{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
1357zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
1358zippingAsync = zipAsyncly
1360-------------------------------------------------------------------------------
1361-- Running Streams, convenience functions specialized to types
1362-------------------------------------------------------------------------------
1364-- | Same as @runStream@.
1366-- @since 0.1.0
1367{-# DEPRECATED runStreamT "Please use runStream instead." #-}
1368runStreamT :: Monad m => SerialT m a -> m ()
1369runStreamT = runStream
1371-- | Same as @runStream . wSerially@.
1373-- @since 0.1.0
1374{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
1375runInterleavedT :: Monad m => InterleavedT m a -> m ()
1376runInterleavedT = runStream . wSerially
1378-- | Same as @runStream . asyncly@.
1380-- @since 0.1.0
1381{-# DEPRECATED runAsyncT "Please use 'runStream . asyncly' instead." #-}
1382runAsyncT :: Monad m => AsyncT m a -> m ()
1383runAsyncT = runStream . asyncly
1385-- | Same as @runStream . parallely@.
1387-- @since 0.1.0
1388{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
1389runParallelT :: Monad m => ParallelT m a -> m ()
1390runParallelT = runStream . parallely
1392-- | Same as @runStream . zipping@.
1394-- @since 0.1.0
1395{-# DEPRECATED runZipStream "Please use 'runStream . zipSerially instead." #-}
1396runZipStream :: Monad m => ZipSerialM m a -> m ()
1397runZipStream = runStream . zipSerially
1399-- | Same as @runStream . zippingAsync@.
1401-- @since 0.1.0
1402{-# DEPRECATED runZipAsync "Please use 'runStream . zipAsyncly instead." #-}
1403runZipAsync :: Monad m => ZipAsyncM m a -> m ()
1404runZipAsync = runStream . zipAsyncly
1406------------------------------------------------------------------------------
1407-- IO Streams
1408------------------------------------------------------------------------------
1410-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
1411-- for more details.
1413-- @since 0.2.0
1414type Serial a = SerialT IO a
1416-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
1417-- documentation for more details.
1419-- @since 0.2.0
1420type WSerial a = WSerialT IO a
1422-- | A serial IO stream of elements of type @a@ with concurrent lookahead. See
1423-- 'AheadT' documentation for more details.
1425-- @since 0.3.0
1426type Ahead a = AheadT IO a
1428-- | A demand driven left biased parallely composing IO stream of elements of
1429-- type @a@. See 'AsyncT' documentation for more details.
1431-- @since 0.2.0
1432type Async a = AsyncT IO a
1434-- | A round robin parallely composing IO stream of elements of type @a@.
1435-- See 'WAsyncT' documentation for more details.
1437-- @since 0.2.0
1438type WAsync a = WAsyncT IO a
1440-- | A parallely composing IO stream of elements of type @a@.
1441-- See 'ParallelT' documentation for more details.
1443-- @since 0.2.0
1444type Parallel a = ParallelT IO a
1446-- | An IO stream whose applicative instance zips streams serially.
1448-- @since 0.2.0
1449type ZipSerial a = ZipSerialM IO a
1451-- | An IO stream whose applicative instance zips streams wAsyncly.
1453-- @since 0.2.0
1454type ZipAsync a = ZipAsyncM IO a
1456------------------------------------------------------------------------------
1457-- Fold Utilities
1458------------------------------------------------------------------------------
1460-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
1461-- container of streams using the specified stream sum operation.
1463-- @foldWith 'async' $ map return [1..3]@
1465-- @since 0.1.0
1466{-# INLINABLE foldWith #-}
1467foldWith :: (IsStream t, Foldable f)
1468 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
1469foldWith f = foldr f nil
1471-- | A variant of 'foldMap' that allows you to map a monadic streaming action
1472-- on a 'Foldable' container and then fold it using the specified stream sum
1473-- operation.
1475-- @foldMapWith 'async' return [1..3]@
1477-- @since 0.1.0
1478{-# INLINABLE foldMapWith #-}
1479foldMapWith :: (IsStream t, Foldable f)
1480 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
1481foldMapWith f g = foldr (f . g) nil
1483-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
1484-- monadic streaming function is the last argument.
1486-- @since 0.1.0
1487{-# INLINABLE forEachWith #-}
1488forEachWith :: (IsStream t, Foldable f)
1489 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
1490forEachWith f xs g = foldr (f . g) nil xs