@@ -46,13 +46,13 @@ module Streamly.Internal.Data.Stream.Concurrent
4646 -- | Stream combinators using a concurrent channel
4747
4848 -- ** Evaluate
49− -- | Evaluate a stream concurrently using a channel.
49+ -- | Evaluates a stream concurrently using a channel.
5050 , eval
5151 , evalWith
5252 -- Add unfoldrM/iterateM?
5353
5454 -- ** Map
55− -- | Use a single channel to evaluate all actions.
55+ -- | Uses a single channel to evaluate all actions.
5656 , mapM
5757 , mapMWith
5858 , sequence
@@ -62,22 +62,32 @@ module Streamly.Internal.Data.Stream.Concurrent
6262 -- ** Combine two
6363 -- | Use a channel for each pair.
6464 -- combine/concur/conjoin
65+ , append2
66+ , interleave2
67+ , ahead2
68+ , parallel2
69+ , parallelFst2
70+ , parallelMin2
71+ , combineWith
72+
73+ -- ** List of streams
74+ -- | Shares a single channel across many streams.
6575 , append
6676 , interleave
6777 , ahead
6878 , parallel
6979 , parallelFst
7080 , parallelMin
71− , combineWith
81+ , concatListWith
7282
73− -- ** Apply
74− -- | Use a separate channel for each application.
83+ -- ** Stream of streams
84+ -- *** Apply
85+ -- | Uses a separate channel for each application.
7586 , apply
7687 , applyWith
7788
78− -- ** Combine many
79− -- | Share a single channel across many streams.
80− , concatList
89+ -- *** Concat
90+ -- | Shares a single channel across many streams.
8191 , concat
8292 , concatWith
8393 , concatMap
@@ -161,7 +171,7 @@ eval :: MonadAsync m => Stream m a -> Stream m a
161171eval = evalWith id
162172
163173-------------------------------------------------------------------------------
164−-- appending two streams
174+-- combining two streams
165175-------------------------------------------------------------------------------
166176
167177{-# INLINE _appendGeneric #-}
@@ -239,68 +249,68 @@ combineWith modifier stream1 stream2 =
239249-- all streams. However, with this operation you can precisely control the
240250-- scheduling by creating arbitrary shape expression trees.
241251--
242−-- >>> append = Async.combineWith id
252+-- >>> append2 = Async.combineWith id
243253--
244254-- The following code finishes in 4 seconds:
245255--
246256-- >>> stream1 = Stream.fromEffect (delay 4)
247257-- >>> stream2 = Stream.fromEffect (delay 2)
248−-- >>> Stream.fold Fold.toList $ stream1 `Async.append` stream2
258+-- >>> Stream.fold Fold.toList $ stream1 `Async.append2` stream2
249259-- 2 sec
250260-- 4 sec
251261-- [2,4]
252262--
253−{-# INLINE append #-}
254−append :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
255−append = combineWith id
263+{-# INLINE append2 #-}
264+append2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
265+append2 = combineWith id
256266
257267-- | Like 'append' but interleaves the streams fairly instead of prioritizing
258268-- the left stream. This schedules all streams in a round robin fashion over
259269-- limited number of threads.
260270--
261−-- >>> interleave = Async.combineWith Async.interleaved
271+-- >>> interleave2 = Async.combineWith Async.interleaved
262272--
263−{-# INLINE interleave #-}
264−interleave :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
265−interleave = combineWith interleaved
273+{-# INLINE interleave2 #-}
274+interleave2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
275+interleave2 = combineWith interleaved
266276
267277-- | Like 'append' but with 'ordered' on.
268278--
269−-- >>> ahead = Async.combineWith Async.ordered
279+-- >>> ahead2 = Async.combineWith Async.ordered
270280--
271−{-# INLINE ahead #-}
272−ahead :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
273−ahead = combineWith ordered
281+{-# INLINE ahead2 #-}
282+ahead2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
283+ahead2 = combineWith ordered
274284
275−-- | Like 'append' but with 'eager' on.
285+-- | Like 'append2' but with 'eager' on.
276286--
277−-- >>> parallel = Async.combineWith Async.eager
287+-- >>> parallel2 = Async.combineWith Async.eager
278288--
279−{-# INLINE parallel #-}
280−parallel :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
281−parallel = combineWith eager
289+{-# INLINE parallel2 #-}
290+parallel2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
291+parallel2 = combineWith eager
282292
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.
284294--
285−-- >>> parallelFst = Async.combineWith (Async.eager . Async.stopWhen Async.FirstStops)
295+-- >>> parallelFst2 = Async.combineWith (Async.eager . Async.stopWhen Async.FirstStops)
286296--
287297-- /Pre-release/
288−{-# INLINE parallelFst #-}
289−parallelFst :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
290−parallelFst = combineWith (eager . stopWhen FirstStops)
298+{-# INLINE parallelFst2 #-}
299+parallelFst2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
300+parallelFst2 = combineWith (eager . stopWhen FirstStops)
291301
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
293303-- stops.
294304--
295−-- >>> parallelMin = Async.combineWith (Async.eager . Async.stopWhen Async.AnyStops)
305+-- >>> parallelMin2 = Async.combineWith (Async.eager . Async.stopWhen Async.AnyStops)
296306--
297307-- /Pre-release/
298−{-# INLINE parallelMin #-}
299−parallelMin :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
300−parallelMin = combineWith (eager . stopWhen AnyStops)
308+{-# INLINE parallelMin2 #-}
309+parallelMin2 :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
310+parallelMin2 = combineWith (eager . stopWhen AnyStops)
301311
302312-------------------------------------------------------------------------------
303−-- concat
313+-- concat streams
304314-------------------------------------------------------------------------------
305315
306316-- | A runner function takes a queuing function @q@ and a stream, it splits the
@@ -327,9 +337,6 @@ mkEnqueue chan runner = do
327337 eagerDispatch chan
328338 in q
329339
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.
332−
333340-- | Takes the head element of the input stream and queues the tail of the
334341-- stream to the channel, then maps the supplied function on the head and
335342-- evaluates the resulting stream.
@@ -489,13 +496,74 @@ concatWith modifier = concatMapWith modifier id
489496concat :: MonadAsync m => Stream m (Stream m a) -> Stream m a
490497concat = concatWith id
491498
499+-------------------------------------------------------------------------------
500+-- concat Lists
501+-------------------------------------------------------------------------------
502+
503+-- | Like 'concatWith' but works on a list of streams.
504+--
505+-- >>> concatListWith modifier = Async.concatWith modifier . Stream.fromList
506+--
507+{-# INLINE concatListWith #-}
508+concatListWith :: MonadAsync m => (Config -> Config) -> [Stream m a] -> Stream m a
509+concatListWith modifier = concatWith modifier . Stream.fromList
510+
492511-- | Like 'concat' but works on a list of streams.
493512--
494−-- >>> concatList = Async.concat . Stream.fromList
513+-- >>> append = Async.concatListWith id
514+--
515+{-# INLINE append #-}
516+append :: MonadAsync m => [Stream m a] -> Stream m a
517+append = concatListWith id
518+
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.
522+--
523+-- >>> interleave = Async.concatListWith Async.interleaved
524+--
525+{-# INLINE interleave #-}
526+interleave :: MonadAsync m => [Stream m a] -> Stream m a
527+interleave = concatListWith interleaved
528+
529+-- | Like 'append' but with 'ordered' on.
530+--
531+-- >>> ahead = Async.concatListWith Async.ordered
532+--
533+{-# INLINE ahead #-}
534+ahead :: MonadAsync m => [Stream m a] -> Stream m a
535+ahead = concatListWith ordered
536+
537+-- | Like 'append' but with 'eager' on.
538+--
539+-- >>> parallel = Async.concatListWith Async.eager
540+--
541+{-# INLINE parallel #-}
542+parallel :: MonadAsync m => [Stream m a] -> Stream m a
543+parallel = concatListWith eager
544+
545+-- | Like 'parallel' but stops the output as soon as the first stream stops.
546+--
547+-- >>> parallelFst = Async.concatListWith (Async.eager . Async.stopWhen Async.FirstStops)
548+--
549+-- /Pre-release/
550+{-# INLINE parallelFst #-}
551+parallelFst :: MonadAsync m => [Stream m a] -> Stream m a
552+parallelFst = concatListWith (eager . stopWhen FirstStops)
553+
554+-- | Like 'parallel' but stops the output as soon as any of the two streams
555+-- stops.
556+--
557+-- >>> parallelMin = Async.concatListWith (Async.eager . Async.stopWhen Async.AnyStops)
495558--
496−{-# INLINE concatList #-}
497−concatList :: MonadAsync m => [Stream m a] -> Stream m a
498−concatList = concat . Stream.fromList
559+-- /Pre-release/
560+{-# INLINE parallelMin #-}
561+parallelMin :: MonadAsync m => [Stream m a] -> Stream m a
562+parallelMin = concatListWith (eager . stopWhen AnyStops)
563+
564+-------------------------------------------------------------------------------
565+-- Applicative
566+-------------------------------------------------------------------------------
499567
500568{-# INLINE applyWith #-}
501569{-# SPECIALIZE applyWith ::
@@ -513,6 +581,10 @@ applyWith modifier stream1 stream2 =
513581apply :: MonadAsync m => Stream m (a -> b) -> Stream m a -> Stream m b
514582apply = applyWith id
515583
584+-------------------------------------------------------------------------------
585+-- Map
586+-------------------------------------------------------------------------------
587+
516588-- |
517589-- >>> mapMWith modifier f = Async.concatMapWith modifier (Stream.fromEffect . f)
518590--