@@ -41,6 +41,11 @@ module Streamly.Internal.Data.Stream.Expand
4141 , interleave
4242 , interleaveFst
4343 , interleaveMin
44+ , interleaveFstSuffix2
45+ , interleaveFst2
46+
47+ -- ** Round Robin
48+ , roundrobin
4449
4550 -- ** Merge
4651 , mergeBy
@@ -140,6 +145,7 @@ import Prelude hiding (concat, concatMap, zipWith)
140145-- >>> :m
141146-- >>> import Data.Either (either)
142147-- >>> import Data.IORef
148+-- >>> import Streamly.Internal.Data.Stream (Stream)
143149-- >>> import Prelude hiding (zipWith, concatMap, concat)
144150-- >>> import qualified Streamly.Data.Array.Unboxed as Array
145151-- >>> import qualified Streamly.Internal.Data.Fold as Fold
@@ -227,6 +233,74 @@ interleaveMin :: Stream m a -> Stream m a -> Stream m a
227233interleaveMin s1 s2 =
228234 fromStreamK $ K.interleaveMin (toStreamK s1) (toStreamK s2)
229235
236+-- | Interleaves the outputs of two streams, yielding elements from each stream
237+-- alternately, starting from the first stream. As soon as the first stream
238+-- finishes, the output stops, discarding the remaining part of the second
239+-- stream. In this case, the last element in the resulting stream would be from
240+-- the second stream. If the second stream finishes early then the first stream
241+-- still continues to yield elements until it finishes.
242+--
243+-- >>> :set -XOverloadedStrings
244+-- >>> import Data.Functor.Identity (Identity)
245+-- >>> Stream.interleaveFstSuffix2 "abc" ",,,," :: Stream Identity Char
246+-- fromList "a,b,c,"
247+-- >>> Stream.interleaveFstSuffix2 "abc" "," :: Stream Identity Char
248+-- fromList "a,bc"
249+--
250+-- 'interleaveFstSuffix2' is a dual of 'interleaveFst2'.
251+--
252+-- Do not use at scale in concatMapWith.
253+--
254+-- /Pre-release/
255+{-# INLINE interleaveFstSuffix2 #-}
256+interleaveFstSuffix2 :: Monad m => Stream m b -> Stream m b -> Stream m b
257+interleaveFstSuffix2 m1 m2 =
258+ fromStreamD $ D.interleaveSuffix (toStreamD m1) (toStreamD m2)
259+
260+-- | Interleaves the outputs of two streams, yielding elements from each stream
261+-- alternately, starting from the first stream and ending at the first stream.
262+-- If the second stream is longer than the first, elements from the second
263+-- stream are infixed with elements from the first stream. If the first stream
264+-- is longer then it continues yielding elements even after the second stream
265+-- has finished.
266+--
267+-- >>> :set -XOverloadedStrings
268+-- >>> import Data.Functor.Identity (Identity)
269+-- >>> Stream.interleaveFst2 "abc" ",,,," :: Stream Identity Char
270+-- fromList "a,b,c"
271+-- >>> Stream.interleaveFst2 "abc" "," :: Stream Identity Char
272+-- fromList "a,bc"
273+--
274+-- 'interleaveFst2' is a dual of 'interleaveFstSuffix2'.
275+--
276+-- Do not use at scale in concatMapWith.
277+--
278+-- /Pre-release/
279+{-# INLINE interleaveFst2 #-}
280+interleaveFst2 :: Monad m => Stream m b -> Stream m b -> Stream m b
281+interleaveFst2 m1 m2 =
282+ fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
283+
284+------------------------------------------------------------------------------
285+-- Scheduling
286+------------------------------------------------------------------------------
287+
288+-- | Schedule the execution of two streams in a fair round-robin manner,
289+-- executing each stream once, alternately. Execution of a stream may not
290+-- necessarily result in an output, a stream may chose to @Skip@ producing an
291+-- element until later giving the other stream a chance to run. Therefore, this
292+-- combinator fairly interleaves the execution of two streams rather than
293+-- fairly interleaving the output of the two streams. This can be useful in
294+-- co-operative multitasking without using explicit threads. This can be used
295+-- as an alternative to `async`.
296+--
297+-- Do not use at scale in concatMapWith.
298+--
299+-- /Pre-release/
300+{-# INLINE roundrobin #-}
301+roundrobin :: Monad m => Stream m b -> Stream m b -> Stream m b
302+roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
303+
230304------------------------------------------------------------------------------
231305-- Merging (sorted streams)
232306------------------------------------------------------------------------------
@@ -361,7 +435,7 @@ unfoldInterleave u m =
361435{-# INLINE unfoldRoundRobin #-}
362436unfoldRoundRobin ::Monad m => Unfold m a b -> Stream m a -> Stream m b
363437unfoldRoundRobin u m =
364− fromStreamD $ D.unfoldManyInterleave u (toStreamD m)
438+ fromStreamD $ D.unfoldManyRoundRobin u (toStreamD m)
365439
366440------------------------------------------------------------------------------
367441-- Combine N Streams - interpose
@@ -407,7 +481,7 @@ interposeSuffix x unf str =
407481-- > unfoldMany unf str =
408482-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
409483
410−-- | 'interleaveInfix' followed by unfold and concat.
484+-- | 'interleaveFst' followed by unfold and concat.
411485--
412486-- /Pre-release/
413487{-# INLINE gintercalate #-}
@@ -438,7 +512,7 @@ intercalate :: Monad m
438512intercalate unf seed str = fromStreamD $
439513 D.unfoldMany unf $ D.intersperse seed (toStreamD str)
440514
441−-- | 'interleaveSuffix' followed by unfold and concat.
515+-- | 'interleaveFstSuffix2' followed by unfold and concat.
442516--
443517-- /Pre-release/
444518{-# INLINE gintercalateSuffix #-}