@@ -54,7 +54,9 @@ module Streamly.Internal.Data.Stream.Concurrent
54 -- ** Generate
54 -- ** Generate
55 -- | Uses a single channel to evaluate all actions.
55 -- | Uses a single channel to evaluate all actions.
57 , replicateM
58 , replicateM
60 -- | Uses a single channel to evaluate all actions.
62 -- | Uses a single channel to evaluate all actions.
@@ -88,7 +90,6 @@ module Streamly.Internal.Data.Stream.Concurrent
89 -- ** Stream of streams
91 -- ** Stream of streams
90 -- *** Apply
92 -- *** Apply
91− -- | Uses a separate channel for each application.
93 , applyWith
94 , applyWith
@@ -176,18 +177,15 @@ evalWithD modifier m = D.Stream step Nothing
176 D.Stop -> D.Stop
177 D.Stop -> D.Stop
179−-- | Like 'eval' but can specify a config modifier to change the concurrent
180+-- | Evaluate a stream asynchronously using a channel and serve the consumer
180−-- channel parameters.
181+-- from the evaluation buffer.
182−-- > evalWith = withChannel (const id)
184{-# INLINE evalWith #-}
183{-# INLINE evalWith #-}
185evalWith :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a
184evalWith :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a
186evalWith modifier input = withChannel modifier input (const id)
185evalWith modifier input = withChannel modifier input (const id)
187 -- Stream.fromStreamD $ evalWithD cfg $ Stream.toStreamD stream
186 -- Stream.fromStreamD $ evalWithD cfg $ Stream.toStreamD stream
189−-- | Evaluate a stream asynchronously using a channel and serve the consumer
188+-- | Definition:
190−-- from the evaluation buffer.
192-- >>> eval = Concur.evalWith id
190-- >>> eval = Concur.evalWith id
@@ -426,25 +424,16 @@ concatMapWithK modifier f input =
426 let g = concatMapWithChanKGeneric modifier
424 let g = concatMapWithChanKGeneric modifier
427 in withChannelK modifier input (`g` f)
425 in withChannelK modifier input (`g` f)
429−-- concatMapWith modifier f stream = concatWith modifier $ fmap f stream
431−-- | Like 'concatMap' but we can also specify the concurrent channel's
432−-- configuration parameters using Config modifiers.
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 =
440− modifier (Stream.toStreamK . f) (Stream.toStreamK stream)
442-- | Map each element of the input to a stream and then concurrently evaluate
427-- | Map each element of the input to a stream and then concurrently evaluate
443-- and concatenate the resulting streams. Multiple streams may be evaluated
428-- and concatenate the resulting streams. Multiple streams may be evaluated
444-- concurrently but earlier streams are perferred. Output from the streams are
429-- concurrently but earlier streams are perferred. Output from the streams are
445-- used as they arrive.
430-- used as they arrive.
447−-- >>> concatMap = Concur.concatMapWith id
432+-- Definition:
434+-- >>> concatMapWith modifier f stream = Concur.concatWith modifier $ fmap f stream
449-- >>> f cfg xs = Stream.fold Fold.toList $ Concur.concatMapWith cfg id $ Stream.fromList xs
438-- >>> f cfg xs = Stream.fold Fold.toList $ Concur.concatMapWith cfg id $ Stream.fromList xs
@@ -477,6 +466,18 @@ concatMapWith modifier f stream =
477-- >>> f (Concur.maxThreads 1) [stream1, stream2]
466-- >>> f (Concur.maxThreads 1) [stream1, stream2]
478-- [1,2,3,4,5,6]
467-- [1,2,3,4,5,6]
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 =
475+ modifier (Stream.toStreamK . f) (Stream.toStreamK stream)
479+-- >>> concatMap = Concur.concatMapWith id
480{-# INLINE concatMap #-}
481{-# INLINE concatMap #-}
481concatMap :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
482concatMap :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
482concatMap = concatMapWith id
483concatMap = concatMapWith id
@@ -503,8 +504,7 @@ concatMap = concatMapWith id
503concatMapInterleave :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
504concatMapInterleave :: MonadAsync m => (a -> Stream m b) -> Stream m a -> Stream m b
504concatMapInterleave = concatMapWith (interleaved True)
505concatMapInterleave = concatMapWith (interleaved True)
506−-- | Like 'concat' but we can also specify the concurrent channel's
507+-- | Evaluate the streams in the input stream concurrently and combine them.
507−-- configuration parameters using Config modifiers.
509-- >>> concatWith modifier = Concur.concatMapWith modifier id
509-- >>> concatWith modifier = Concur.concatMapWith modifier id
@@ -513,7 +513,7 @@ concatWith :: MonadAsync m =>
513 (Config -> Config) -> Stream m (Stream m a) -> Stream m a
513 (Config -> Config) -> Stream m (Stream m a) -> Stream m a
514concatWith modifier = concatMapWith modifier id
514concatWith modifier = concatMapWith modifier id
516−-- | Evaluate the streams in the input stream concurrently and combine them.
516+-- | Definition:
518-- >>> concat = Concur.concatWith id
518-- >>> concat = Concur.concatWith id
@@ -578,6 +578,8 @@ parallelFst = concatListWith (eager True . stopWhen FirstStops)
578-- | Like 'parallel' but stops the output as soon as any of the two streams
578-- | Like 'parallel' but stops the output as soon as any of the two streams
581-- >>> parallelMin = Concur.concatListWith (Concur.eager True . Concur.stopWhen Concur.AnyStops)
583-- >>> parallelMin = Concur.concatListWith (Concur.eager True . Concur.stopWhen Concur.AnyStops)
583{-# INLINE parallelMin #-}
585{-# INLINE parallelMin #-}
@@ -588,6 +590,8 @@ parallelMin = concatListWith (eager True . stopWhen AnyStops)
588-- Applicative
590-- Applicative
589-------------------------------------------------------------------------------
591-------------------------------------------------------------------------------
593+-- | Apply an argument stream to a function stream concurrently. Uses a
594+-- shared channel for all individual applications within a stream application.
591{-# INLINE applyWith #-}
595{-# INLINE applyWith #-}
592{-# SPECIALIZE applyWith ::
596{-# SPECIALIZE applyWith ::
593 (Config -> Config) -> Stream IO (a -> b) -> Stream IO a -> Stream IO b #-}
597 (Config -> Config) -> Stream IO (a -> b) -> Stream IO a -> Stream IO b #-}
@@ -609,15 +613,41 @@ apply = applyWith id
609-------------------------------------------------------------------------------
613-------------------------------------------------------------------------------
612-- >>> mapMWith modifier f = Concur.concatMapWith modifier (Stream.fromEffect . f)
618-- >>> mapMWith modifier f = Concur.concatMapWith modifier (Stream.fromEffect . f)
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::
624+-- >>> f x = delay x >> return x
625+-- >>> Stream.fold Fold.toList $ Concur.mapMWith (Concur.ordered True) f $ Stream.fromList [3,2,1]
614{-# INLINE mapMWith #-}
631{-# INLINE mapMWith #-}
615mapMWith :: MonadAsync m =>
632mapMWith :: MonadAsync m =>
616 (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b
633 (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b
617mapMWith modifier f = concatMapWith modifier (Stream.fromEffect . f)
634mapMWith modifier f = concatMapWith modifier (Stream.fromEffect . f)
620-- >>> mapM = Concur.mapMWith id
639-- >>> mapM = Concur.mapMWith id
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::
644+-- >>> f x = delay x >> return x
645+-- >>> Stream.fold Fold.toList $ Concur.mapM f $ Stream.fromList [3,2,1]
621{-# INLINE mapM #-}
651{-# INLINE mapM #-}
622mapM :: MonadAsync m => (a -> m b) -> Stream m a -> Stream m b
652mapM :: MonadAsync m => (a -> m b) -> Stream m a -> Stream m b
623mapM = mapMWith id
653mapM = mapMWith id
@@ -664,21 +694,48 @@ zipWith f = zipWithM (\a b -> return $ f a b)
664-------------------------------------------------------------------------------
694-------------------------------------------------------------------------------
699+-- >>> repeatMWith cfg = Concur.sequenceWith cfg . Stream.repeat
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
667−-- >>> repeatM = Concur.sequence . Stream.repeat
709+-- >>> repeatM = Concur.repeatMWith id
669−-- Generate a stream by repeatedly executing a monadic action forever. The
670−-- number of actions that are executed concurrently is limited by 'maxThreads'.
671{-# INLINE repeatM #-}
711{-# INLINE repeatM #-}
672repeatM :: MonadAsync m => m a -> Stream m a
712repeatM :: MonadAsync m => m a -> Stream m a
673−repeatM = sequence . Stream.repeat
713+repeatM = repeatMWith id
715+-- | Generate a stream by concurrently performing a monadic action @n@ times.
719+-- >>> replicateMWith cfg n = Concur.sequenceWith cfg . Stream.replicate n
721+-- Example, 'replicateMWith' in the following example executes all the
722+-- replicated actions concurrently, thus taking only 1 second:
724+-- >>> Stream.fold Fold.drain $ Concur.replicateMWith id 10 $ delay 1
727+{-# INLINE replicateMWith #-}
728+replicateMWith :: MonadAsync m => (Config -> Config) -> Int -> m a -> Stream m a
729+replicateMWith cfg n = sequenceWith cfg . Stream.replicate n
676−-- >>> replicateM n = Concur.sequence . Stream.replicate n
734+-- >>> replicateM n = Concur.replicateMWith id
678−-- Generate a stream by concurrently performing a monadic action @n@ times.
679{-# INLINE replicateM #-}
736{-# INLINE replicateM #-}
680replicateM :: MonadAsync m => Int -> m a -> Stream m a
737replicateM :: MonadAsync m => Int -> m a -> Stream m a
681−replicateM n = sequence . Stream.replicate n
738+replicateM = replicateMWith id
683-------------------------------------------------------------------------------
740-------------------------------------------------------------------------------
684-- Reactive
741-- Reactive