@@ -54,7 +54,9 @@ module Streamly.Internal.Data.Stream.Concurrent
5454 -- ** Generate
5555 -- | Uses a single channel to evaluate all actions.
5656 , repeatM
57+ , repeatMWith
5758 , replicateM
59+ , replicateMWith
5860
5961 -- ** Map
6062 -- | Uses a single channel to evaluate all actions.
@@ -88,7 +90,6 @@ module Streamly.Internal.Data.Stream.Concurrent
8890
8991 -- ** Stream of streams
9092 -- *** Apply
91− -- | Uses a separate channel for each application.
9293 , apply
9394 , applyWith
9495
@@ -176,18 +177,15 @@ evalWithD modifier m = D.Stream step Nothing
176177 D.Stop -> D.Stop
177178-}
178179
179−-- | Like 'eval' but can specify a config modifier to change the concurrent
180−-- channel parameters.
181−--
182−-- > evalWith = withChannel (const id)
180+-- | Evaluate a stream asynchronously using a channel and serve the consumer
181+-- from the evaluation buffer.
183182--
184183{-# INLINE evalWith #-}
185184evalWith :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a
186185evalWith modifier input = withChannel modifier input (const id)
187186 -- Stream.fromStreamD $ evalWithD cfg $ Stream.toStreamD stream
188187
189−-- | Evaluate a stream asynchronously using a channel and serve the consumer
190−-- from the evaluation buffer.
188+-- | Definition:
191189--
192190-- >>> eval = Concur.evalWith id
193191--
@@ -426,25 +424,16 @@ concatMapWithK modifier f input =
426424 let g = concatMapWithChanKGeneric modifier
427425 in withChannelK modifier input (`g` f)
428426
429−-- concatMapWith modifier f stream = concatWith modifier $ fmap f stream
430−
431−-- | Like 'concatMap' but we can also specify the concurrent channel's
432−-- configuration parameters using Config modifiers.
433−--
434−{-# INLINE concatMapWith #-}
435−concatMapWith :: MonadAsync m =>
436− (Config -> Config) -> (a -> Stream m b) -> Stream m a -> Stream m b
437−concatMapWith modifier f stream =
438− Stream.fromStreamK
439− $ concatMapWithK
440− modifier (Stream.toStreamK . f) (Stream.toStreamK stream)
441−
442427-- | Map each element of the input to a stream and then concurrently evaluate
443428-- and concatenate the resulting streams. Multiple streams may be evaluated
444429-- concurrently but earlier streams are perferred. Output from the streams are
445430-- used as they arrive.
446431--
447−-- >>> concatMap = Concur.concatMapWith id
432+-- Definition:
433+--
434+-- >>> concatMapWith modifier f stream = Concur.concatWith modifier $ fmap f stream
435+--
436+-- Examples:
448437--
449438-- >>> f cfg xs = Stream.fold Fold.toList $ Concur.concatMapWith cfg id $ Stream.fromList xs
450439--
@@ -477,6 +466,18 @@ concatMapWith modifier f stream =
477466-- >>> f (Concur.maxThreads 1) [stream1, stream2]
478467-- [1,2,3,4,5,6]
479468--
469+{-# INLINE concatMapWith #-}
470+concatMapWith :: MonadAsync m =>
471+ (Config -> Config) -> (a -> Stream m b) -> Stream m a -> Stream m b
472+concatMapWith modifier f stream =
473+ Stream.fromStreamK
474+ $ concatMapWithK
475+ modifier (Stream.toStreamK . f) (Stream.toStreamK stream)
476+
477+-- | Definition:
478+--
479+-- >>> concatMap = Concur.concatMapWith id
480+--
480481{-# INLINE concatMap #-}
481482concatMap :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
482483concatMap = concatMapWith id
@@ -503,8 +504,7 @@ concatMap = concatMapWith id
503504concatMapInterleave :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
504505concatMapInterleave = concatMapWith (interleaved True)
505506
506−-- | Like 'concat' but we can also specify the concurrent channel's
507−-- configuration parameters using Config modifiers.
507+-- | Evaluate the streams in the input stream concurrently and combine them.
508508--
509509-- >>> concatWith modifier = Concur.concatMapWith modifier id
510510--
@@ -513,7 +513,7 @@ concatWith :: MonadAsync m =>
513513 (Config -> Config) -> Stream m (Stream m a) -> Stream m a
514514concatWith modifier = concatMapWith modifier id
515515
516−-- | Evaluate the streams in the input stream concurrently and combine them.
516+-- | Definition:
517517--
518518-- >>> concat = Concur.concatWith id
519519--
@@ -578,6 +578,8 @@ parallelFst = concatListWith (eager True . stopWhen FirstStops)
578578-- | Like 'parallel' but stops the output as soon as any of the two streams
579579-- stops.
580580--
581+-- Definition:
582+--
581583-- >>> parallelMin = Concur.concatListWith (Concur.eager True . Concur.stopWhen Concur.AnyStops)
582584--
583585{-# INLINE parallelMin #-}
@@ -588,6 +590,8 @@ parallelMin = concatListWith (eager True . stopWhen AnyStops)
588590-- Applicative
589591-------------------------------------------------------------------------------
590592
593+-- | Apply an argument stream to a function stream concurrently. Uses a
594+-- shared channel for all individual applications within a stream application.
591595{-# INLINE applyWith #-}
592596{-# SPECIALIZE applyWith ::
593597 (Config -> Config) -> Stream IO (a -> b) -> Stream IO a -> Stream IO b #-}
@@ -609,15 +613,41 @@ apply = applyWith id
609613-------------------------------------------------------------------------------
610614
611615-- |
616+-- Definition:
617+--
612618-- >>> mapMWith modifier f = Concur.concatMapWith modifier (Stream.fromEffect . f)
613619--
620+-- Example, the following example finishes in 1 second as all actions run in
621+-- parallel. Even though results are available out of order they are ordered
622+-- due to the config option::
623+--
624+-- >>> f x = delay x >> return x
625+-- >>> Stream.fold Fold.toList $ Concur.mapMWith (Concur.ordered True) f $ Stream.fromList [3,2,1]
626+-- 1 sec
627+-- 2 sec
628+-- 3 sec
629+-- [3,2,1]
630+--
614631{-# INLINE mapMWith #-}
615632mapMWith :: MonadAsync m =>
616633 (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b
617634mapMWith modifier f = concatMapWith modifier (Stream.fromEffect . f)
618635
619636-- |
637+-- Definition:
638+--
620639-- >>> mapM = Concur.mapMWith id
640+--
641+-- Example, the following example finishes in 1 second as all actions run in
642+-- parallel, by default, the results are output as soon as they are available::
643+--
644+-- >>> f x = delay x >> return x
645+-- >>> Stream.fold Fold.toList $ Concur.mapM f $ Stream.fromList [3,2,1]
646+-- 1 sec
647+-- 2 sec
648+-- 3 sec
649+-- [1,2,3]
650+--
621651{-# INLINE mapM #-}
622652mapM :: MonadAsync m => (a -> m b) -> Stream m a -> Stream m b
623653mapM = mapMWith id
@@ -664,21 +694,48 @@ zipWith f = zipWithM (\a b -> return $ f a b)
664694-------------------------------------------------------------------------------
665695
666696-- |
667−-- >>> repeatM = Concur.sequence . Stream.repeat
697+-- Definition:
698+--
699+-- >>> repeatMWith cfg = Concur.sequenceWith cfg . Stream.repeat
700+--
701+-- Generate a stream by repeatedly executing a monadic action forever.
702+{-# INLINE repeatMWith #-}
703+repeatMWith :: MonadAsync m => (Config -> Config) -> m a -> Stream m a
704+repeatMWith cfg = sequenceWith cfg . Stream.repeat
705+
706+-- |
707+-- Definition:
708+--
709+-- >>> repeatM = Concur.repeatMWith id
668710--
669−-- Generate a stream by repeatedly executing a monadic action forever. The
670−-- number of actions that are executed concurrently is limited by 'maxThreads'.
671711{-# INLINE repeatM #-}
672712repeatM :: MonadAsync m => m a -> Stream m a
673−repeatM = sequence . Stream.repeat
713+repeatM = repeatMWith id
714+
715+-- | Generate a stream by concurrently performing a monadic action @n@ times.
716+--
717+-- Definition:
718+--
719+-- >>> replicateMWith cfg n = Concur.sequenceWith cfg . Stream.replicate n
720+--
721+-- Example, 'replicateMWith' in the following example executes all the
722+-- replicated actions concurrently, thus taking only 1 second:
723+--
724+-- >>> Stream.fold Fold.drain $ Concur.replicateMWith id 10 $ delay 1
725+-- ...
726+--
727+{-# INLINE replicateMWith #-}
728+replicateMWith :: MonadAsync m => (Config -> Config) -> Int -> m a -> Stream m a
729+replicateMWith cfg n = sequenceWith cfg . Stream.replicate n
674730
675731-- |
676−-- >>> replicateM n = Concur.sequence . Stream.replicate n
732+-- Definition:
733+--
734+-- >>> replicateM n = Concur.replicateMWith id
677735--
678−-- Generate a stream by concurrently performing a monadic action @n@ times.
679736{-# INLINE replicateM #-}
680737replicateM :: MonadAsync m => Int -> m a -> Stream m a
681−replicateM n = sequence . Stream.replicate n
738+replicateM = replicateMWith id
682739
683740-------------------------------------------------------------------------------
684741-- Reactive