on 082a4fc help sign in
streamly/src/Streamly/Streams.hs
1474 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
58 -- * IO Streams
59 , Serial
60 , WSerial
61 , Ahead
62 , Async
63 , WAsync
64 , Parallel
65 , ZipSerial
66 , ZipAsync
68 -- * Stream Transformers
69 , SerialT
70 , StreamT -- deprecated
71 , WSerialT
72 , InterleavedT -- deprecated
73 , AheadT
74 , AsyncT
75 , WAsyncT
76 , ParallelT
77 , ZipStream -- deprecated
78 , ZipSerialM
79 , ZipAsyncM
81 -- * Type Adapters
82 , serially -- deprecated
83 , wSerially
84 , interleaving -- deprecated
85 , aheadly
86 , asyncly
87 , wAsyncly
88 , parallely
89 , zipSerially
90 , zipping -- deprecated
91 , zipAsyncly
92 , zippingAsync -- deprecated
93 , adapt
95 -- * Running Streams
96 , runStreamT -- deprecated
97 , runInterleavedT -- deprecated
98 , runAsyncT -- deprecated
99 , runParallelT -- deprecated
100 , runZipStream -- deprecated
101 , runZipAsync -- deprecated
103 -- * Fold Utilities
104 , foldWith
105 , foldMapWith
106 , forEachWith
107 )
108where
110import Control.Monad (ap)
111import Control.Monad.Base (MonadBase (..), liftBaseDefault)
112import Control.Monad.Catch (MonadThrow, throwM)
113-- import Control.Monad.Error.Class (MonadError(..))
114import Control.Monad.IO.Class (MonadIO(..))
115import Control.Monad.Reader.Class (MonadReader(..))
116import Control.Monad.State.Class (MonadState(..))
117import Control.Monad.Trans.Class (MonadTrans (lift))
118import Data.Semigroup (Semigroup(..))
119import Streamly.Core ( MonadAsync , SVar,
120 SVarStyle(..))
121import qualified Streamly.Core as S
123------------------------------------------------------------------------------
124-- Types that can behave as a Stream
125------------------------------------------------------------------------------
127infixr 5 `consM`
128infixr 5 |:
130-- | Class of types that can represent a stream of elements of some type 'a' in
131-- some monad 'm'.
132--
133-- @since 0.2.0
134class IsStream t where
135 toStream :: t m a -> S.Stream m a
136 fromStream :: S.Stream m a -> t m a
137 -- | Constructs a stream by adding a monadic action at the head of an
138 -- existing stream. For example:
139 --
140 -- @
141 -- > toList $ getLine \`consM` getLine \`consM` nil
142 -- hello
143 -- world
144 -- ["hello","world"]
145 -- @
146 --
147 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
148 --
149 -- @since 0.2.0
150 consM :: MonadAsync m => m a -> t m a -> t m a
151 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
152 -- to remember that @|@ comes before ':'.
153 --
154 -- @
155 -- > toList $ getLine |: getLine |: nil
156 -- hello
157 -- world
158 -- ["hello","world"]
159 -- @
160 --
161 -- @
162 -- let delay = threadDelay 1000000 >> print 1
163 -- runStream $ serially $ delay |: delay |: delay |: nil
164 -- runStream $ parallely $ delay |: delay |: delay |: nil
165 -- @
166 --
167 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
168 --
169 -- @since 0.2.0
170 (|:) :: MonadAsync m => m a -> t m a -> t m a
171 -- We can define (|:) just as 'consM' but it is defined explicitly for each
172 -- type because we want to use SPECIALIZE pragma on the definition.
174-- | Same as 'IsStream'.
175--
176-- @since 0.1.0
177{-# DEPRECATED Streaming "Please use IsStream instead." #-}
178type Streaming = IsStream
180------------------------------------------------------------------------------
181-- Constructing a stream
182------------------------------------------------------------------------------
184-- | An empty stream.
185--
186-- @
187-- > toList nil
188-- []
189-- @
190--
191-- @since 0.1.0
192nil :: IsStream t => t m a
193nil = fromStream S.nil
195-- | Constructs a stream by adding a monadic action at the head of an existing
196-- stream. For example:
197--
198-- @
199-- > toList $ getLine \`consM` getLine \`consM` nil
200-- hello
201-- world
202-- ["hello","world"]
203-- @
204--
205-- @since 0.2.0
206consMSerial :: (IsStream t, Monad m) => m a -> t m a -> t m a
207consMSerial m r = fromStream $ S.consM m (toStream r)
209infixr 5 `cons`
211-- | Construct a stream by adding a pure value at the head of an existing
212-- stream. For pure values it can be faster than 'consM'. For example:
213--
214-- @
215-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
216-- [1,2,3]
217-- @
218--
219-- @since 0.1.0
220cons :: IsStream t => a -> t m a -> t m a
221cons a r = fromStream $ S.cons a (toStream r)
223infixr 5 .:
225-- | Operator equivalent of 'cons'.
226--
227-- @
228-- > toList $ 1 .: 2 .: 3 .: nil
229-- [1,2,3]
230-- @
231--
232-- @since 0.1.1
233(.:) :: IsStream t => a -> t m a -> t m a
234(.:) = cons
236-- | Build a stream from its church encoding. The function passed maps
237-- directly to the underlying representation of the stream type. The second
238-- parameter to the function is the "yield" function yielding a value and the
239-- remaining stream if any otherwise 'Nothing'. The third parameter is to
240-- represent an "empty" stream.
241streamBuild :: IsStream t
242 => (forall r. Maybe (SVar m a)
243 -> (a -> t m a -> m r)
244 -> (a -> m r)
245 -> m r
246 -> m r)
247 -> t m a
248streamBuild k = fromStream $ S.Stream $ \svr stp sng yld ->
249 let yield a r = yld a (toStream r)
250 in k svr yield sng stp
252-- | Build a singleton stream from a callback function.
253fromCallback :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
254fromCallback k = fromStream $ S.Stream $ \_ _ sng _ -> k sng
256-- | Read an SVar to get a stream.
257fromSVar :: (MonadAsync m, IsStream t) => SVar m a -> t m a
258fromSVar sv = fromStream $ S.fromStreamVar sv
260------------------------------------------------------------------------------
261-- Destroying a stream
262------------------------------------------------------------------------------
264-- | Fold a stream using its church encoding. The second argument is the "step"
265-- function consuming an element and the remaining stream, if any. The third
266-- argument is for consuming an "empty" stream that yields nothing.
267streamFold
268 :: IsStream t
269 => Maybe (SVar m a)
270 -> (a -> t m a -> m r)
271 -> (a -> m r)
272 -> m r
273 -> t m a
274 -> m r
275streamFold svr step single blank m =
276 let yield a x = step a (fromStream x)
277 in (S.runStream (toStream m)) svr blank single yield
279-- | Run a streaming composition, discard the results. By default it interprets
280-- the stream as 'SerialT', to run other types of streams use the type adapting
281-- combinators for example @runStream . 'asyncly'@.
282--
283-- @since 0.2.0
284runStream :: Monad m => SerialT m a -> m ()
285runStream m = go (toStream m)
286 where
287 go m1 =
288 let stop = return ()
289 single _ = return ()
290 yield _ r = go r
291 in (S.runStream m1) Nothing stop single yield
293-- | Same as 'runStream'
294--
295-- @since 0.1.0
296{-# DEPRECATED runStreaming "Please use runStream instead." #-}
297runStreaming :: (Monad m, IsStream t) => t m a -> m ()
298runStreaming = runStream . adapt
300-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
301-- be read back from the SVar using 'fromSVar'.
302toSVar :: (IsStream t, MonadAsync m) => SVar m a -> t m a -> m ()
303toSVar sv m = S.toStreamVar sv (toStream m)
305------------------------------------------------------------------------------
306-- Transformation
307------------------------------------------------------------------------------
309-- XXX Get rid of this?
310-- | Make a stream asynchronous, triggers the computation and returns a stream
311-- in the underlying monad representing the output generated by the original
312-- computation. The returned action is exhaustible and must be drained once. If
313-- not drained fully we may have a thread blocked forever and once exhausted it
314-- will always return 'empty'.
315--
316-- @since 0.2.0
317mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
318mkAsync m = do
319 sv <- S.newStreamVar1 AsyncVar (toStream m)
320 return $ fromSVar sv
322{-# INLINE applyWith #-}
323applyWith :: (IsStream t, MonadAsync m)
324 => SVarStyle -> (t m a -> t m b) -> t m a -> t m b
325applyWith style f x = fromStream $
326 S.applyWith style (toStream . f . fromStream) (toStream x)
328{-# INLINE runWith #-}
329runWith :: (IsStream t, MonadAsync m)
330 => SVarStyle -> (t m a -> m b) -> t m a -> m b
331runWith style f x = S.runWith style (f . fromStream) (toStream x)
333-- | Parallel function application operator for streams; just like the regular
334-- function application operator '$' except that it is concurrent. The
335-- following code prints a value every second even though each stage adds a 1
336-- second delay.
337--
338--
339-- @
340-- runStream $
341-- S.mapM (\\x -> threadDelay 1000000 >> print x)
342-- |$ S.repeatM (threadDelay 1000000 >> return 1)
343-- @
344--
345-- /Concurrent/
346--
347-- @since 0.3.0
348{-# INLINE (|$) #-}
349(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b
350f |$ x = applyWith ParallelVar f x
352-- | Parallel reverse function application operator for streams; just like the
353-- regular reverse function application operator '&' except that it is
354-- concurrent.
355--
356-- @
357-- runStream $
358-- S.repeatM (threadDelay 1000000 >> return 1)
359-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
360-- @
361--
362-- /Concurrent/
363--
364-- @since 0.3.0
365{-# INLINE (|&) #-}
366(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
367x |& f = f |$ x
369-- | Parallel function application operator; applies a @run@ or @fold@ function
370-- to a stream such that the fold consumer and the stream producer run in
371-- parallel. A @run@ or @fold@ function reduces the stream to a value in the
372-- underlying monad.
373--
374-- @
375-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
376-- <| S.repeatM (threadDelay 1000000 >> return 1)
377-- @
378--
379-- /Concurrent/
380--
381-- @since 0.3.0
382{-# INLINE (<|) #-}
383(<|) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b
384f <| x = runWith ParallelVar f x
386-- | Parallel reverse function application operator for applying a run or fold
387-- functions to a stream. Just like '<|' except that the operands are reversed.
388--
389-- @
390-- S.repeatM (threadDelay 1000000 >> return 1)
391-- |> S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
392-- @
393--
394-- /Concurrent/
395--
396-- @since 0.3.0
397{-# INLINE (|>) #-}
398(|>) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
399x |> f = f <| x
401------------------------------------------------------------------------------
402-- CPP macros for common instances
403------------------------------------------------------------------------------
405-- XXX use template haskell instead and include Monoid and IsStream instances
406-- as well.
408withLocal :: MonadReader r m => (r -> r) -> S.Stream m a -> S.Stream m a
409withLocal f m =
410 S.Stream $ \svr stp sng yld ->
411 let single = local f . sng
412 yield a r = local f $ yld a (withLocal f r)
413 in (S.runStream m) svr (local f stp) single yield
415{-
416-- XXX handle and test cross thread state transfer
417withCatchError
418 :: MonadError e m
419 => S.Stream m a -> (e -> S.Stream m a) -> S.Stream m a
420withCatchError m h =
421 S.Stream $ \svr stp sng yld ->
422 let run x = S.runStream x svr stp sng yield
423 handle r = r `catchError` \e -> run $ h e
424 yield a r = yld a (withCatchError r h)
425 in handle $ run m
426-}
428#define MONADPARALLEL , MonadAsync m
430#define MONAD_APPLICATIVE_INSTANCE(STREAM,CONSTRAINT) \
431instance (Monad m CONSTRAINT) => Applicative (STREAM m) where { \
432 pure = STREAM . S.singleton; \
433 (<*>) = ap }
435#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
436instance (MonadBase b m, Monad m CONSTRAINT) => MonadBase b (STREAM m) where {\
437 liftBase = liftBaseDefault }; \
438 \
439instance (MonadIO m CONSTRAINT) => MonadIO (STREAM m) where { \
440 liftIO = lift . liftIO }; \
441 \
442instance (MonadThrow m CONSTRAINT) => MonadThrow (STREAM m) where { \
443 throwM = lift . throwM }; \
444 \
445{- \
446instance (MonadError e m CONSTRAINT) => MonadError e (STREAM m) where { \
447 throwError = lift . throwError; \
448 catchError m h = \
449 fromStream $ withCatchError (toStream m) (\e -> toStream $ h e) }; \
450-} \
451 \
452instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
453 ask = lift ask; \
454 local f m = fromStream $ withLocal f (toStream m) }; \
455 \
456instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
457 get = lift get; \
458 put x = lift (put x); \
459 state k = lift (state k) }
461------------------------------------------------------------------------------
462-- SerialT
463------------------------------------------------------------------------------
465-- | Deep serial composition or serial composition with depth first traversal.
466-- The 'Semigroup' instance of 'SerialT' appends two streams serially in a
467-- depth first manner, yielding all elements from the first stream, and then
468-- all elements from the second stream.
469--
470-- @
471-- import Streamly
472-- import qualified "Streamly.Prelude" as S
473--
474-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
475-- @
476-- @
477-- [1,2,3,4]
478-- @
479--
480-- The 'Monad' instance runs the /monadic continuation/ for each
481-- element of the stream, serially.
482--
483-- @
484-- main = 'runStream' . 'serially' $ do
485-- x <- return 1 \<\> return 2
486-- S.once $ print x
487-- @
488-- @
489-- 1
490-- 2
491-- @
492--
493-- 'SerialT' nests streams serially in a depth first manner.
494--
495-- @
496-- main = 'runStream' . 'serially' $ do
497-- x <- return 1 \<\> return 2
498-- y <- return 3 \<\> return 4
499-- S.once $ print (x, y)
500-- @
501-- @
502-- (1,3)
503-- (1,4)
504-- (2,3)
505-- (2,4)
506-- @
507--
508-- This behavior of 'SerialT' is exactly like a list transformer. We call the
509-- monadic code being run for each element of the stream a monadic
510-- continuation. In imperative paradigm we can think of this composition as
511-- nested @for@ loops and the monadic continuation is the body of the loop. The
512-- loop iterates for all elements of the stream.
513--
514-- The 'serially' combinator can be omitted as the default stream type is
515-- 'SerialT'.
516-- Note that serial composition with depth first traversal can be used to
517-- combine an infinite number of streams as it explores only one stream at a
518-- time.
519--
520-- @since 0.2.0
521newtype SerialT m a = SerialT {getSerialT :: S.Stream m a}
522 deriving (Semigroup, Monoid, Functor, MonadTrans)
524-- |
525-- @since 0.1.0
526{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
527type StreamT = SerialT
529instance IsStream SerialT where
530 toStream = getSerialT
531 fromStream = SerialT
533 {-# INLINE consM #-}
534 {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
535 consM :: Monad m => m a -> SerialT m a -> SerialT m a
536 consM = consMSerial
538 {-# INLINE (|:) #-}
539 {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
540 (|:) :: Monad m => m a -> SerialT m a -> SerialT m a
541 (|:) = consMSerial
543------------------------------------------------------------------------------
544-- Semigroup
545------------------------------------------------------------------------------
547-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
548-- Appends two streams sequentially, yielding all elements from the first
549-- stream, and then all elements from the second stream.
550--
551-- @since 0.2.0
552{-# INLINE serial #-}
553serial :: IsStream t => t m a -> t m a -> t m a
554serial m1 m2 = fromStream $ S.serial (toStream m1) (toStream m2)
556------------------------------------------------------------------------------
557-- Monad
558------------------------------------------------------------------------------
560instance Monad m => Monad (SerialT m) where
561 return = pure
562 (SerialT (S.Stream m)) >>= f = SerialT $ S.Stream $ \_ stp sng yld ->
563 let run x = (S.runStream x) Nothing stp sng yld
564 single a = run $ toStream (f a)
565 yield a r = run $ toStream $ f a <> (fromStream r >>= f)
566 in m Nothing stp single yield
568------------------------------------------------------------------------------
569-- Other instances
570------------------------------------------------------------------------------
572MONAD_APPLICATIVE_INSTANCE(SerialT,)
573MONAD_COMMON_INSTANCES(SerialT,)
575------------------------------------------------------------------------------
576-- WSerialT
577------------------------------------------------------------------------------
579-- | Wide serial composition or serial composition with a breadth first
580-- traversal. The 'Semigroup' instance of 'WSerialT' traverses
581-- the two streams in a breadth first manner. In other words, it interleaves
582-- two streams, yielding one element from each stream alternately.
583--
584-- @
585-- import Streamly
586-- import qualified "Streamly.Prelude" as S
587--
588-- main = ('toList' . 'wSerially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
589-- @
590-- @
591-- [1,3,2,4]
592-- @
593--
594-- Similarly, the 'Monad' instance interleaves the iterations of the
595-- inner and the outer loop, nesting loops in a breadth first manner.
596--
597--
598-- @
599-- main = 'runStream' . 'wSerially' $ do
600-- x <- return 1 \<\> return 2
601-- y <- return 3 \<\> return 4
602-- S.once $ print (x, y)
603-- @
604-- @
605-- (1,3)
606-- (2,3)
607-- (1,4)
608-- (2,4)
609-- @
610--
611-- Note that a serial composition with breadth first traversal can only combine
612-- a finite number of streams as it needs to retain state for each unfinished
613-- stream.
614--
615-- @since 0.2.0
616newtype WSerialT m a = WSerialT {getWSerialT :: S.Stream m a}
617 deriving (Functor, MonadTrans)
619-- |
620-- @since 0.1.0
621{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
622type InterleavedT = WSerialT
624instance IsStream WSerialT where
625 toStream = getWSerialT
626 fromStream = WSerialT
628 {-# INLINE consM #-}
629 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
630 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
631 consM = consMSerial
633 {-# INLINE (|:) #-}
634 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
635 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
636 (|:) = consMSerial
638------------------------------------------------------------------------------
639-- Semigroup
640------------------------------------------------------------------------------
642-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
643-- Interleaves two streams, yielding one element from each stream alternately.
644--
645-- @since 0.2.0
646{-# INLINE wSerial #-}
647wSerial :: IsStream t => t m a -> t m a -> t m a
648wSerial m1 m2 = fromStream $ S.wSerial (toStream m1) (toStream m2)
650instance Semigroup (WSerialT m a) where
651 (<>) = wSerial
653infixr 5 <=>
655-- | Same as 'wSerial'.
656--
657-- @since 0.1.0
658{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
659{-# INLINE (<=>) #-}
660(<=>) :: IsStream t => t m a -> t m a -> t m a
661(<=>) = wSerial
663------------------------------------------------------------------------------
664-- Monoid
665------------------------------------------------------------------------------
667instance Monoid (WSerialT m a) where
668 mempty = nil
669 mappend = (<>)
671------------------------------------------------------------------------------
672-- Monad
673------------------------------------------------------------------------------
675instance Monad m => Monad (WSerialT m) where
676 return = pure
677 (WSerialT (S.Stream m)) >>= f = WSerialT $ S.Stream $ \_ stp sng yld ->
678 let run x = (S.runStream x) Nothing stp sng yld
679 single a = run $ toStream (f a)
680 yield a r = run $ toStream $ f a <> (fromStream r >>= f)
681 in m Nothing stp single yield
683------------------------------------------------------------------------------
684-- Other instances
685------------------------------------------------------------------------------
687MONAD_APPLICATIVE_INSTANCE(WSerialT,)
688MONAD_COMMON_INSTANCES(WSerialT,)
690------------------------------------------------------------------------------
691-- AheadT
692------------------------------------------------------------------------------
694-- | Deep ahead composition or ahead composition with depth first traversal.
695-- The semigroup composition of 'AheadT' appends streams in a depth first
696-- manner just like 'SerialT' except that it can produce elements concurrently
697-- ahead of time. It is like 'AsyncT' except that 'AsyncT' produces the output
698-- as it arrives whereas 'AheadT' orders the output in the traversal order.
699--
700-- @
701-- main = ('toList' . 'aheadly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
702-- @
703-- @
704-- [1,2,3,4]
705-- @
706--
707-- Any exceptions generated by a constituent stream are propagated to the
708-- output stream.
709--
710-- Similarly, the monad instance of 'AheadT' may run each iteration
711-- concurrently ahead of time but presents the results in the same order as
712-- 'SerialT'.
713--
714-- @
715-- import "Streamly"
716-- import qualified "Streamly.Prelude" as S
717-- import Control.Concurrent
718--
719-- main = 'runStream' . 'aheadly' $ do
720-- n <- return 3 \<\> return 2 \<\> return 1
721-- S.once $ do
722-- threadDelay (n * 1000000)
723-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
724-- @
725-- @
726-- ThreadId 40: Delay 1
727-- ThreadId 39: Delay 2
728-- ThreadId 38: Delay 3
729-- @
730--
731-- All iterations may run in the same thread if they do not block.
732--
733-- Note that ahead composition with depth first traversal can be used to
734-- combine infinite number of streams as it explores only a bounded number of
735-- streams at a time.
736--
737-- @since 0.3.0
738newtype AheadT m a = AheadT {getAheadT :: S.Stream m a}
739 deriving (Functor, MonadTrans)
741instance IsStream AheadT where
742 toStream = getAheadT
743 fromStream = AheadT
745 {-# INLINE consM #-}
746 {-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
747 consM m r = fromStream $ S.consMAhead m (toStream r)
749 {-# INLINE (|:) #-}
750 {-# SPECIALIZE (|:) :: IO a -> AheadT IO a -> AheadT IO a #-}
751 (|:) = consM
753------------------------------------------------------------------------------
754-- Semigroup
755------------------------------------------------------------------------------
757-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
758-- Merges two streams sequentially but with concurrent lookahead.
759--
760-- @since 0.3.0
761{-# INLINE ahead #-}
762ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
763ahead m1 m2 = fromStream $ S.ahead (toStream m1) (toStream m2)
765instance MonadAsync m => Semigroup (AheadT m a) where
766 (<>) = ahead
768------------------------------------------------------------------------------
769-- Monoid
770------------------------------------------------------------------------------
772instance MonadAsync m => Monoid (AheadT m a) where
773 mempty = nil
774 mappend = (<>)
776------------------------------------------------------------------------------
777-- Monad
778------------------------------------------------------------------------------
780{-# INLINE aheadbind #-}
781aheadbind
782 :: MonadAsync m
783 => S.Stream m a
784 -> (a -> S.Stream m b)
785 -> S.Stream m b
786aheadbind m f = go m
787 where
788 go (S.Stream g) =
789 S.Stream $ \ctx stp sng yld ->
790 let run x = (S.runStream x) ctx stp sng yld
791 single a = run $ f a
792 yield a r = run $ f a `S.ahead` go r
793 in g Nothing stp single yield
795instance MonadAsync m => Monad (AheadT m) where
796 return = pure
797 (AheadT m) >>= f = AheadT $ aheadbind m (getAheadT . f)
799------------------------------------------------------------------------------
800-- Other instances
801------------------------------------------------------------------------------
803MONAD_APPLICATIVE_INSTANCE(AheadT,MONADPARALLEL)
804MONAD_COMMON_INSTANCES(AheadT, MONADPARALLEL)
806------------------------------------------------------------------------------
807-- AsyncT
808------------------------------------------------------------------------------
810-- | Deep async composition or async composition with depth first traversal. In
811-- a left to right 'Semigroup' composition it tries to yield elements from the
812-- left stream as long as it can, but it can run the right stream in parallel
813-- if it needs to, based on demand. The right stream can be run if the left
814-- stream blocks on IO or cannot produce elements fast enough for the consumer.
815--
816-- @
817-- main = ('toList' . 'asyncly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
818-- @
819-- @
820-- [1,2,3,4]
821-- @
822--
823-- Any exceptions generated by a constituent stream are propagated to the
824-- output stream. The output and exceptions from a single stream are guaranteed
825-- to arrive in the same order in the resulting stream as they were generated
826-- in the input stream. However, the relative ordering of elements from
827-- different streams in the resulting stream can vary depending on scheduling
828-- and generation delays.
829--
830-- Similarly, the monad instance of 'AsyncT' /may/ run each iteration
831-- concurrently based on demand. More concurrent iterations are started only
832-- if the previous iterations are not able to produce enough output for the
833-- consumer.
834--
835-- @
836-- import "Streamly"
837-- import qualified "Streamly.Prelude" as S
838-- import Control.Concurrent
839--
840-- main = 'runStream' . 'asyncly' $ do
841-- n <- return 3 \<\> return 2 \<\> return 1
842-- S.once $ do
843-- threadDelay (n * 1000000)
844-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
845-- @
846-- @
847-- ThreadId 40: Delay 1
848-- ThreadId 39: Delay 2
849-- ThreadId 38: Delay 3
850-- @
851--
852-- All iterations may run in the same thread if they do not block.
853--
854-- Note that async composition with depth first traversal can be used to
855-- combine infinite number of streams as it explores only a bounded number of
856-- streams at a time.
857--
858-- @since 0.1.0
859newtype AsyncT m a = AsyncT {getAsyncT :: S.Stream m a}
860 deriving (Functor, MonadTrans)
862instance IsStream AsyncT where
863 toStream = getAsyncT
864 fromStream = AsyncT
866 {-# INLINE consM #-}
867 {-# SPECIALIZE consM :: IO a -> AsyncT IO a -> AsyncT IO a #-}
868 consM m r = fromStream $ S.consMAsync m (toStream r)
870 {-# INLINE (|:) #-}
871 {-# SPECIALIZE (|:) :: IO a -> AsyncT IO a -> AsyncT IO a #-}
872 (|:) = consM
874------------------------------------------------------------------------------
875-- Semigroup
876------------------------------------------------------------------------------
878-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
879-- Merges two streams possibly concurrently, preferring the
880-- elements from the left one when available.
881--
882-- @since 0.2.0
883{-# INLINE async #-}
884async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
885async m1 m2 = fromStream $ S.async (toStream m1) (toStream m2)
887instance MonadAsync m => Semigroup (AsyncT m a) where
888 (<>) = async
890------------------------------------------------------------------------------
891-- Monoid
892------------------------------------------------------------------------------
894instance MonadAsync m => Monoid (AsyncT m a) where
895 mempty = nil
896 mappend = (<>)
898------------------------------------------------------------------------------
899-- Monad
900------------------------------------------------------------------------------
902{-# INLINE parbind #-}
903parbind
904 :: (forall c. S.Stream m c -> S.Stream m c -> S.Stream m c)
905 -> S.Stream m a
906 -> (a -> S.Stream m b)
907 -> S.Stream m b
908parbind par m f = go m
909 where
910 go (S.Stream g) =
911 S.Stream $ \ctx stp sng yld ->
912 let run x = (S.runStream x) ctx stp sng yld
913 single a = run $ f a
914 yield a r = run $ f a `par` go r
915 in g Nothing stp single yield
917instance MonadAsync m => Monad (AsyncT m) where
918 return = pure
919 (AsyncT m) >>= f = AsyncT $ parbind S.async m (getAsyncT . f)
921------------------------------------------------------------------------------
922-- Other instances
923------------------------------------------------------------------------------
925MONAD_APPLICATIVE_INSTANCE(AsyncT,MONADPARALLEL)
926MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
928------------------------------------------------------------------------------
929-- WAsyncT
930------------------------------------------------------------------------------
932-- | Wide async composition or async composition with breadth first traversal.
933-- The Semigroup instance of 'WAsyncT' concurrently /traverses/ the composed
934-- streams using a depth first travesal or in a round robin fashion, yielding
935-- elements from both streams alternately.
936--
937-- @
938-- main = ('toList' . 'wAsyncly' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
939-- @
940-- @
941-- [1,3,2,4]
942-- @
943--
944-- Any exceptions generated by a constituent stream are propagated to the
945-- output stream. The output and exceptions from a single stream are guaranteed
946-- to arrive in the same order in the resulting stream as they were generated
947-- in the input stream. However, the relative ordering of elements from
948-- different streams in the resulting stream can vary depending on scheduling
949-- and generation delays.
950--
951-- Similarly, the 'Monad' instance of 'WAsyncT' runs /all/ iterations fairly
952-- concurrently using a round robin scheduling.
953--
954-- @
955-- import "Streamly"
956-- import qualified "Streamly.Prelude" as S
957-- import Control.Concurrent
958--
959-- main = 'runStream' . 'wAsyncly' $ do
960-- n <- return 3 \<\> return 2 \<\> return 1
961-- S.once $ do
962-- threadDelay (n * 1000000)
963-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
964-- @
965-- @
966-- ThreadId 40: Delay 1
967-- ThreadId 39: Delay 2
968-- ThreadId 38: Delay 3
969-- @
970--
971-- Unlike 'AsyncT' all iterations are guaranteed to run fairly
972-- concurrently, unconditionally.
973--
974-- Note that async composition with breadth first traversal can only combine a
975-- finite number of streams as it needs to retain state for each unfinished
976-- stream.
977--
978-- @since 0.2.0
979newtype WAsyncT m a = WAsyncT {getWAsyncT :: S.Stream m a}
980 deriving (Functor, MonadTrans)
982instance IsStream WAsyncT where
983 toStream = getWAsyncT
984 fromStream = WAsyncT
986 {-# INLINE consM #-}
987 {-# SPECIALIZE consM :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
988 consM m r = fromStream $ S.consMWAsync m (toStream r)
990 {-# INLINE (|:) #-}
991 {-# SPECIALIZE (|:) :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
992 (|:) = consM
994------------------------------------------------------------------------------
995-- Semigroup
996------------------------------------------------------------------------------
998-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
999-- Merges two streams concurrently choosing elements from both fairly.
1001-- @since 0.2.0
1002{-# INLINE wAsync #-}
1003wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
1004wAsync m1 m2 = fromStream $ S.wAsync (toStream m1) (toStream m2)
1006instance MonadAsync m => Semigroup (WAsyncT m a) where
1007 (<>) = wAsync
1009------------------------------------------------------------------------------
1010-- Monoid
1011------------------------------------------------------------------------------
1013instance MonadAsync m => Monoid (WAsyncT m a) where
1014 mempty = nil
1015 mappend = (<>)
1017------------------------------------------------------------------------------
1018-- Monad
1019------------------------------------------------------------------------------
1021instance MonadAsync m => Monad (WAsyncT m) where
1022 return = pure
1023 (WAsyncT m) >>= f =
1024 WAsyncT $ parbind S.wAsync m (getWAsyncT . f)
1026------------------------------------------------------------------------------
1027-- Other instances
1028------------------------------------------------------------------------------
1030MONAD_APPLICATIVE_INSTANCE(WAsyncT,MONADPARALLEL)
1031MONAD_COMMON_INSTANCES(WAsyncT, MONADPARALLEL)
1033------------------------------------------------------------------------------
1034-- ParallelT
1035------------------------------------------------------------------------------
1037-- | Async composition with simultaneous traversal of all streams.
1039-- The Semigroup instance of 'ParallelT' concurrently /merges/ two streams,
1040-- running both strictly concurrently and yielding elements from both streams
1041-- as they arrive. When multiple streams are combined using 'ParallelT' each
1042-- one is evaluated in its own thread and the results produced are presented in
1043-- the combined stream on a first come first serve basis.
1045-- 'AsyncT' and 'WAsyncT' are /concurrent lookahead streams/ each with a
1046-- specific type of consumption pattern (depth first or breadth first). Since
1047-- they are lookahead, they may introduce certain default latency in starting
1048-- more concurrent tasks for efficiency reasons or may put a default limitation
1049-- on the resource consumption (e.g. number of concurrent threads for
1050-- lookahead). If we look at the implementation detail, they both can share a
1051-- pool of worker threads to evaluate the streams in the desired pattern and at
1052-- the desired rate. However, 'ParallelT' uses a separate runtime thread to
1053-- evaluate each stream.
1055-- 'WAsyncT' is similar to 'ParallelT', as both of them evaluate the
1056-- constituent streams fairly in a round robin fashion.
1057-- However, the key difference is that 'WAsyncT' is lazy or pull driven
1058-- whereas 'ParallelT' is strict or push driven. 'ParallelT' immediately
1059-- starts concurrent evaluation of both the streams (in separate threads) and
1060-- later picks the results whereas 'WAsyncT' may wait for a certain latency
1061-- threshold before initiating concurrent evaluation of the next stream. The
1062-- concurrent scheduling of the next stream or the degree of concurrency is
1063-- driven by the feedback from the consumer. In case of 'ParallelT' each stream
1064-- is evaluated in a separate thread and results are /pushed/ to a shared
1065-- output buffer, the evaluation rate is controlled by blocking when the buffer
1066-- is full.
1068-- Concurrent lookahead streams are generally more efficient than
1069-- 'ParallelT' and can work pretty efficiently even for smaller tasks because
1070-- they do not necessarily use a separate thread for each task. So they should
1071-- be preferred over 'ParallelT' especially when efficiency is a concern and
1072-- simultaneous strict evaluation is not a requirement. 'ParallelT' is useful
1073-- for cases when the streams are required to be evaluated simultaneously
1074-- irrespective of how the consumer consumes them e.g. when we want to race
1075-- two tasks and want to start both strictly at the same time or if we have
1076-- timers in the parallel tasks and our results depend on the timers being
1077-- started at the same time. We can say that 'ParallelT' is almost the same
1078-- (modulo some implementation differences) as 'WAsyncT' when the latter is
1079-- used with unlimited lookahead and zero latency in initiating lookahead.
1081-- @
1082-- main = ('toList' . 'parallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
1083-- @
1084-- @
1085-- [1,3,2,4]
1086-- @
1088-- When streams with more than one element are merged, it yields whichever
1089-- stream yields first without any bias, unlike the 'Async' style streams.
1091-- Any exceptions generated by a constituent stream are propagated to the
1092-- output stream. The output and exceptions from a single stream are guaranteed
1093-- to arrive in the same order in the resulting stream as they were generated
1094-- in the input stream. However, the relative ordering of elements from
1095-- different streams in the resulting stream can vary depending on scheduling
1096-- and generation delays.
1098-- Similarly, the 'Monad' instance of 'ParallelT' runs /all/ iterations
1099-- of the loop concurrently.
1101-- @
1102-- import "Streamly"
1103-- import qualified "Streamly.Prelude" as S
1104-- import Control.Concurrent
1106-- main = 'runStream' . 'parallely' $ do
1107-- n <- return 3 \<\> return 2 \<\> return 1
1108-- S.once $ do
1109-- threadDelay (n * 1000000)
1110-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
1111-- @
1112-- @
1113-- ThreadId 40: Delay 1
1114-- ThreadId 39: Delay 2
1115-- ThreadId 38: Delay 3
1116-- @
1118-- Note that parallel composition can only combine a finite number of
1119-- streams as it needs to retain state for each unfinished stream.
1121-- @since 0.1.0
1122newtype ParallelT m a = ParallelT {getParallelT :: S.Stream m a}
1123 deriving (Functor, MonadTrans)
1125instance IsStream ParallelT where
1126 toStream = getParallelT
1127 fromStream = ParallelT
1129 {-# INLINE consM #-}
1130 {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
1131 consM m r = fromStream $ S.consMParallel m (toStream r)
1133 {-# INLINE (|:) #-}
1134 {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
1135 (|:) = consM
1137------------------------------------------------------------------------------
1138-- Semigroup
1139------------------------------------------------------------------------------
1141-- | Polymorphic version of the 'Semigroup' operation '<>' of 'ParallelT'
1142-- Merges two streams concurrently.
1144-- @since 0.2.0
1145{-# INLINE parallel #-}
1146parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
1147parallel m1 m2 = fromStream $ S.parallel (toStream m1) (toStream m2)
1149instance MonadAsync m => Semigroup (ParallelT m a) where
1150 (<>) = parallel
1152------------------------------------------------------------------------------
1153-- Monoid
1154------------------------------------------------------------------------------
1156instance MonadAsync m => Monoid (ParallelT m a) where
1157 mempty = nil
1158 mappend = (<>)
1160------------------------------------------------------------------------------
1161-- Monad
1162------------------------------------------------------------------------------
1164instance MonadAsync m => Monad (ParallelT m) where
1165 return = pure
1166 (ParallelT m) >>= f = ParallelT $ parbind S.parallel m (getParallelT . f)
1168------------------------------------------------------------------------------
1169-- Other instances
1170------------------------------------------------------------------------------
1172MONAD_APPLICATIVE_INSTANCE(ParallelT,MONADPARALLEL)
1173MONAD_COMMON_INSTANCES(ParallelT, MONADPARALLEL)
1175------------------------------------------------------------------------------
1176-- Serially Zipping Streams
1177------------------------------------------------------------------------------
1179-- | The applicative instance of 'ZipSerialM' zips a number of streams serially
1180-- i.e. it produces one element from each stream serially and then zips all
1181-- those elements.
1183-- @
1184-- main = (toList . 'zipSerially' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
1185-- where s1 = fromFoldable [1, 2]
1186-- s2 = fromFoldable [3, 4]
1187-- s3 = fromFoldable [5, 6]
1188-- @
1189-- @
1190-- [(1,3,5),(2,4,6)]
1191-- @
1193-- The 'Semigroup' instance of this type works the same way as that of
1194-- 'SerialT'.
1196-- @since 0.2.0
1197newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: S.Stream m a}
1198 deriving (Functor, Semigroup, Monoid)
1200-- |
1201-- @since 0.1.0
1202{-# DEPRECATED ZipStream "Please use 'ZipSerialM' instead." #-}
1203type ZipStream = ZipSerialM
1205instance IsStream ZipSerialM where
1206 toStream = getZipSerialM
1207 fromStream = ZipSerialM
1209 {-# INLINE consM #-}
1210 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
1211 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
1212 consM = consMSerial
1214 {-# INLINE (|:) #-}
1215 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
1216 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
1217 (|:) = consMSerial
1219instance Monad m => Applicative (ZipSerialM m) where
1220 pure = ZipSerialM . S.repeat
1221 m1 <*> m2 = fromStream $ S.zipWith id (toStream m1) (toStream m2)
1223------------------------------------------------------------------------------
1224-- Parallely Zipping Streams
1225------------------------------------------------------------------------------
1227-- | Like 'ZipSerialM' but zips in parallel, it generates all the elements to
1228-- be zipped concurrently.
1230-- @
1231-- main = (toList . 'zipAsyncly' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
1232-- where s1 = fromFoldable [1, 2]
1233-- s2 = fromFoldable [3, 4]
1234-- s3 = fromFoldable [5, 6]
1235-- @
1236-- @
1237-- [(1,3,5),(2,4,6)]
1238-- @
1240-- The 'Semigroup' instance of this type works the same way as that of
1241-- 'SerialT'.
1243-- @since 0.2.0
1244newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: S.Stream m a}
1245 deriving (Functor, Semigroup, Monoid)
1247instance IsStream ZipAsyncM where
1248 toStream = getZipAsyncM
1249 fromStream = ZipAsyncM
1251 {-# INLINE consM #-}
1252 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
1253 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
1254 consM = consMSerial
1256 {-# INLINE (|:) #-}
1257 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
1258 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
1259 (|:) = consMSerial
1261instance MonadAsync m => Applicative (ZipAsyncM m) where
1262 pure = ZipAsyncM . S.repeat
1263 m1 <*> m2 = fromStream $ S.zipAsyncWith id (toStream m1) (toStream m2)
1265-------------------------------------------------------------------------------
1266-- Type adapting combinators
1267-------------------------------------------------------------------------------
1269-- | Adapt any specific stream type to any other specific stream type.
1271-- @since 0.1.0
1272adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
1273adapt = fromStream . toStream
1275-- | Fix the type of a polymorphic stream as 'SerialT'.
1277-- @since 0.1.0
1278serially :: IsStream t => SerialT m a -> t m a
1279serially = adapt
1281-- | Fix the type of a polymorphic stream as 'WSerialT'.
1283-- @since 0.2.0
1284wSerially :: IsStream t => WSerialT m a -> t m a
1285wSerially = adapt
1287-- | Same as 'wSerially'.
1289-- @since 0.1.0
1290{-# DEPRECATED interleaving "Please use wSerially instead." #-}
1291interleaving :: IsStream t => WSerialT m a -> t m a
1292interleaving = wSerially
1294-- | Fix the type of a polymorphic stream as 'AheadT'.
1296-- @since 0.3.0
1297aheadly :: IsStream t => AheadT m a -> t m a
1298aheadly = adapt
1300-- | Fix the type of a polymorphic stream as 'AsyncT'.
1302-- @since 0.1.0
1303asyncly :: IsStream t => AsyncT m a -> t m a
1304asyncly = adapt
1306-- | Fix the type of a polymorphic stream as 'WAsyncT'.
1308-- @since 0.2.0
1309wAsyncly :: IsStream t => WAsyncT m a -> t m a
1310wAsyncly = adapt
1312-- | Fix the type of a polymorphic stream as 'ParallelT'.
1314-- @since 0.1.0
1315parallely :: IsStream t => ParallelT m a -> t m a
1316parallely = adapt
1318-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
1320-- @since 0.2.0
1321zipSerially :: IsStream t => ZipSerialM m a -> t m a
1322zipSerially = adapt
1324-- | Same as 'zipSerially'.
1326-- @since 0.1.0
1327{-# DEPRECATED zipping "Please use zipSerially instead." #-}
1328zipping :: IsStream t => ZipSerialM m a -> t m a
1329zipping = zipSerially
1331-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
1333-- @since 0.2.0
1334zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
1335zipAsyncly = adapt
1337-- | Same as 'zipAsyncly'.
1339-- @since 0.1.0
1340{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
1341zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
1342zippingAsync = zipAsyncly
1344-------------------------------------------------------------------------------
1345-- Running Streams, convenience functions specialized to types
1346-------------------------------------------------------------------------------
1348-- | Same as @runStream@.
1350-- @since 0.1.0
1351{-# DEPRECATED runStreamT "Please use runStream instead." #-}
1352runStreamT :: Monad m => SerialT m a -> m ()
1353runStreamT = runStream
1355-- | Same as @runStream . wSerially@.
1357-- @since 0.1.0
1358{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
1359runInterleavedT :: Monad m => InterleavedT m a -> m ()
1360runInterleavedT = runStream . wSerially
1362-- | Same as @runStream . asyncly@.
1364-- @since 0.1.0
1365{-# DEPRECATED runAsyncT "Please use 'runStream . asyncly' instead." #-}
1366runAsyncT :: Monad m => AsyncT m a -> m ()
1367runAsyncT = runStream . asyncly
1369-- | Same as @runStream . parallely@.
1371-- @since 0.1.0
1372{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
1373runParallelT :: Monad m => ParallelT m a -> m ()
1374runParallelT = runStream . parallely
1376-- | Same as @runStream . zipping@.
1378-- @since 0.1.0
1379{-# DEPRECATED runZipStream "Please use 'runStream . zipSerially instead." #-}
1380runZipStream :: Monad m => ZipSerialM m a -> m ()
1381runZipStream = runStream . zipSerially
1383-- | Same as @runStream . zippingAsync@.
1385-- @since 0.1.0
1386{-# DEPRECATED runZipAsync "Please use 'runStream . zipAsyncly instead." #-}
1387runZipAsync :: Monad m => ZipAsyncM m a -> m ()
1388runZipAsync = runStream . zipAsyncly
1390------------------------------------------------------------------------------
1391-- IO Streams
1392------------------------------------------------------------------------------
1394-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
1395-- for more details.
1397-- @since 0.2.0
1398type Serial a = SerialT IO a
1400-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
1401-- documentation for more details.
1403-- @since 0.2.0
1404type WSerial a = WSerialT IO a
1406-- | A serial IO stream of elements of type @a@ with concurrent lookahead. See
1407-- 'AheadT' documentation for more details.
1409-- @since 0.3.0
1410type Ahead a = AheadT IO a
1412-- | A demand driven left biased parallely composing IO stream of elements of
1413-- type @a@. See 'AsyncT' documentation for more details.
1415-- @since 0.2.0
1416type Async a = AsyncT IO a
1418-- | A round robin parallely composing IO stream of elements of type @a@.
1419-- See 'WAsyncT' documentation for more details.
1421-- @since 0.2.0
1422type WAsync a = WAsyncT IO a
1424-- | A parallely composing IO stream of elements of type @a@.
1425-- See 'ParallelT' documentation for more details.
1427-- @since 0.2.0
1428type Parallel a = ParallelT IO a
1430-- | An IO stream whose applicative instance zips streams serially.
1432-- @since 0.2.0
1433type ZipSerial a = ZipSerialM IO a
1435-- | An IO stream whose applicative instance zips streams wAsyncly.
1437-- @since 0.2.0
1438type ZipAsync a = ZipAsyncM IO a
1440------------------------------------------------------------------------------
1441-- Fold Utilities
1442------------------------------------------------------------------------------
1444-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
1445-- container of streams using the specified stream sum operation.
1447-- @foldWith 'async' $ map return [1..3]@
1449-- @since 0.1.0
1450{-# INLINABLE foldWith #-}
1451foldWith :: (IsStream t, Foldable f)
1452 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
1453foldWith f = foldr f nil
1455-- | A variant of 'foldMap' that allows you to map a monadic streaming action
1456-- on a 'Foldable' container and then fold it using the specified stream sum
1457-- operation.
1459-- @foldMapWith 'async' return [1..3]@
1461-- @since 0.1.0
1462{-# INLINABLE foldMapWith #-}
1463foldMapWith :: (IsStream t, Foldable f)
1464 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
1465foldMapWith f g = foldr (f . g) nil
1467-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
1468-- monadic streaming function is the last argument.
1470-- @since 0.1.0
1471{-# INLINABLE forEachWith #-}
1472forEachWith :: (IsStream t, Foldable f)
1473 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
1474forEachWith f xs g = foldr (f . g) nil xs