@@ -46,13 +46,13 @@ module Streamly.Internal.Data.Stream.Concurrent
46 -- | Stream combinators using a concurrent channel
46 -- | Stream combinators using a concurrent channel
48 -- ** Evaluate
48 -- ** Evaluate
49− -- | Evaluate a stream concurrently using a channel.
49+ -- | Evaluates a stream concurrently using a channel.
51 , evalWith
51 , evalWith
52 -- Add unfoldrM/iterateM?
52 -- Add unfoldrM/iterateM?
55− -- | Use a single channel to evaluate all actions.
55+ -- | Uses a single channel to evaluate all actions.
57 , mapMWith
57 , mapMWith
58 , sequence
58 , sequence
@@ -62,22 +62,32 @@ module Streamly.Internal.Data.Stream.Concurrent
62 -- ** Combine two
62 -- ** Combine two
63 -- | Use a channel for each pair.
63 -- | Use a channel for each pair.
64 -- combine/concur/conjoin
64 -- combine/concur/conjoin
73+ -- ** List of streams
74+ -- | Shares a single channel across many streams.
66 , interleave
76 , interleave
68 , parallel
78 , parallel
69 , parallelFst
79 , parallelFst
70 , parallelMin
80 , parallelMin
71− , combineWith
81+ , concatListWith
83+ -- ** Stream of streams
73− -- ** Apply
84+ -- *** Apply
74− -- | Use a separate channel for each application.
85+ -- | Uses a separate channel for each application.
76 , applyWith
87 , applyWith
78− -- ** Combine many
89+ -- *** Concat
79− -- | Share a single channel across many streams.
90+ -- | Shares a single channel across many streams.
82 , concatWith
92 , concatWith
83 , concatMap
93 , concatMap
@@ -161,7 +171,7 @@ eval :: MonadAsync m => Stream m a -> Stream m a
161eval = evalWith id
171eval = evalWith id
163-------------------------------------------------------------------------------
173-------------------------------------------------------------------------------
164−-- appending two streams
174+-- combining two streams
165-------------------------------------------------------------------------------
175-------------------------------------------------------------------------------
167{-# INLINE _appendGeneric #-}
177{-# INLINE _appendGeneric #-}
@@ -239,68 +249,68 @@ combineWith modifier stream1 stream2 =
239-- all streams. However, with this operation you can precisely control the
249-- all streams. However, with this operation you can precisely control the
240-- scheduling by creating arbitrary shape expression trees.
250-- scheduling by creating arbitrary shape expression trees.
242−-- >>> append = Async.combineWith id
252+-- >>> append2 = Async.combineWith id
244-- The following code finishes in 4 seconds:
254-- The following code finishes in 4 seconds:
246-- >>> stream1 = Stream.fromEffect (delay 4)
256-- >>> stream1 = Stream.fromEffect (delay 4)
247-- >>> stream2 = Stream.fromEffect (delay 2)
257-- >>> stream2 = Stream.fromEffect (delay 2)
248−-- >>> Stream.fold Fold.toList $ stream1 `Async.append` stream2
258+-- >>> Stream.fold Fold.toList $ stream1 `Async.append2` stream2
253−{-# INLINE append #-}
263+{-# INLINE append2 #-}
254−append :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
264+append2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
255−append = combineWith id
265+append2 = combineWith id
257-- | Like 'append' but interleaves the streams fairly instead of prioritizing
267-- | Like 'append' but interleaves the streams fairly instead of prioritizing
258-- the left stream. This schedules all streams in a round robin fashion over
268-- the left stream. This schedules all streams in a round robin fashion over
259-- limited number of threads.
269-- limited number of threads.
261−-- >>> interleave = Async.combineWith Async.interleaved
271+-- >>> interleave2 = Async.combineWith Async.interleaved
263−{-# INLINE interleave #-}
273+{-# INLINE interleave2 #-}
264−interleave :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
274+interleave2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
265−interleave = combineWith interleaved
275+interleave2 = combineWith interleaved
267-- | Like 'append' but with 'ordered' on.
277-- | Like 'append' but with 'ordered' on.
269−-- >>> ahead = Async.combineWith Async.ordered
279+-- >>> ahead2 = Async.combineWith Async.ordered
271−{-# INLINE ahead #-}
281+{-# INLINE ahead2 #-}
272−ahead :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
282+ahead2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
273−ahead = combineWith ordered
283+ahead2 = combineWith ordered
275−-- | Like 'append' but with 'eager' on.
285+-- | Like 'append2' but with 'eager' on.
277−-- >>> parallel = Async.combineWith Async.eager
287+-- >>> parallel2 = Async.combineWith Async.eager
279−{-# INLINE parallel #-}
289+{-# INLINE parallel2 #-}
280−parallel :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
290+parallel2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
281−parallel = combineWith eager
291+parallel2 = combineWith eager
283−-- | Like 'parallel' but stops the output as soon as the first stream stops.
293+-- | Like 'parallel2' but stops the output as soon as the first stream stops.
285−-- >>> parallelFst = Async.combineWith (Async.eager . Async.stopWhen Async.FirstStops)
295+-- >>> parallelFst2 = Async.combineWith (Async.eager . Async.stopWhen Async.FirstStops)
287-- /Pre-release/
297-- /Pre-release/
288−{-# INLINE parallelFst #-}
298+{-# INLINE parallelFst2 #-}
289−parallelFst :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
299+parallelFst2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
290−parallelFst = combineWith (eager . stopWhen FirstStops)
300+parallelFst2 = combineWith (eager . stopWhen FirstStops)
292−-- | Like 'parallel' but stops the output as soon as any of the two streams
302+-- | Like 'parallel2' but stops the output as soon as any of the two streams
295−-- >>> parallelMin = Async.combineWith (Async.eager . Async.stopWhen Async.AnyStops)
305+-- >>> parallelMin2 = Async.combineWith (Async.eager . Async.stopWhen Async.AnyStops)
297-- /Pre-release/
307-- /Pre-release/
298−{-# INLINE parallelMin #-}
308+{-# INLINE parallelMin2 #-}
299−parallelMin :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
309+parallelMin2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
300−parallelMin = combineWith (eager . stopWhen AnyStops)
310+parallelMin2 = combineWith (eager . stopWhen AnyStops)
302-------------------------------------------------------------------------------
312-------------------------------------------------------------------------------
303−-- concat
313+-- concat streams
304-------------------------------------------------------------------------------
314-------------------------------------------------------------------------------
306-- | A runner function takes a queuing function @q@ and a stream, it splits the
316-- | A runner function takes a queuing function @q@ and a stream, it splits the
@@ -327,9 +337,6 @@ mkEnqueue chan runner = do
327 eagerDispatch chan
337 eagerDispatch chan
330−-- XXX Can be renamed to concatMapWithK if we move concatMapWithK to higher
331−-- level module. We can keep only Channel based ops in this module.
333-- | Takes the head element of the input stream and queues the tail of the
340-- | Takes the head element of the input stream and queues the tail of the
334-- stream to the channel, then maps the supplied function on the head and
341-- stream to the channel, then maps the supplied function on the head and
335-- evaluates the resulting stream.
342-- evaluates the resulting stream.
@@ -489,13 +496,74 @@ concatWith modifier = concatMapWith modifier id
489concat :: MonadAsync m => Stream m (Stream m a) -> Stream m a
496concat :: MonadAsync m => Stream m (Stream m a) -> Stream m a
490concat = concatWith id
497concat = concatWith id
499+-------------------------------------------------------------------------------
501+-------------------------------------------------------------------------------
503+-- | Like 'concatWith' but works on a list of streams.
505+-- >>> concatListWith modifier = Async.concatWith modifier . Stream.fromList
507+{-# INLINE concatListWith #-}
508+concatListWith :: MonadAsync m => (Config -> Config) -> [Stream m a] -> Stream m a
509+concatListWith modifier = concatWith modifier . Stream.fromList
492-- | Like 'concat' but works on a list of streams.
511-- | Like 'concat' but works on a list of streams.
494−-- >>> concatList = Async.concat . Stream.fromList
513+-- >>> append = Async.concatListWith id
515+{-# INLINE append #-}
516+append :: MonadAsync m => [Stream m a] -> Stream m a
517+append = concatListWith id
519+-- | Like 'append' but interleaves the streams fairly instead of prioritizing
520+-- the left stream. This schedules all streams in a round robin fashion over
521+-- limited number of threads.
523+-- >>> interleave = Async.concatListWith Async.interleaved
525+{-# INLINE interleave #-}
526+interleave :: MonadAsync m => [Stream m a] -> Stream m a
527+interleave = concatListWith interleaved
529+-- | Like 'append' but with 'ordered' on.
531+-- >>> ahead = Async.concatListWith Async.ordered
534+ahead :: MonadAsync m => [Stream m a] -> Stream m a
535+ahead = concatListWith ordered
537+-- | Like 'append' but with 'eager' on.
539+-- >>> parallel = Async.concatListWith Async.eager
541+{-# INLINE parallel #-}
542+parallel :: MonadAsync m => [Stream m a] -> Stream m a
543+parallel = concatListWith eager
545+-- | Like 'parallel' but stops the output as soon as the first stream stops.
547+-- >>> parallelFst = Async.concatListWith (Async.eager . Async.stopWhen Async.FirstStops)
550+{-# INLINE parallelFst #-}
551+parallelFst :: MonadAsync m => [Stream m a] -> Stream m a
552+parallelFst = concatListWith (eager . stopWhen FirstStops)
554+-- | Like 'parallel' but stops the output as soon as any of the two streams
557+-- >>> parallelMin = Async.concatListWith (Async.eager . Async.stopWhen Async.AnyStops)
496−{-# INLINE concatList #-}
559+-- /Pre-release/
560+{-# INLINE parallelMin #-}
497−concatList :: MonadAsync m => [Stream m a] -> Stream m a
561+parallelMin :: MonadAsync m => [Stream m a] -> Stream m a
498−concatList = concat . Stream.fromList
562+parallelMin = concatListWith (eager . stopWhen AnyStops)
564+-------------------------------------------------------------------------------
566+-------------------------------------------------------------------------------
500{-# INLINE applyWith #-}
568{-# INLINE applyWith #-}
501{-# SPECIALIZE applyWith ::
569{-# SPECIALIZE applyWith ::
@@ -513,6 +581,10 @@ applyWith modifier stream1 stream2 =
513apply :: MonadAsync m => Stream m (a -> b) -> Stream m a -> Stream m b
581apply :: MonadAsync m => Stream m (a -> b) -> Stream m a -> Stream m b
514apply = applyWith id
582apply = applyWith id
584+-------------------------------------------------------------------------------
586+-------------------------------------------------------------------------------
517-- >>> mapMWith modifier f = Async.concatMapWith modifier (Stream.fromEffect . f)
589-- >>> mapMWith modifier f = Async.concatMapWith modifier (Stream.fromEffect . f)