@@ -33,7 +33,7 @@ module Streamly.Internal.Prelude
3333 -- ** From Values
3434 , yield
3535 , yieldM
36− , K.repeat
36+ , repeat
3737 , repeatM
3838 , replicate
3939 , replicateM
@@ -205,9 +205,9 @@ module Streamly.Internal.Prelude
205205 , insertBy
206206 , intersperseM
207207 , intersperse
208− , insertAfterEach
208+ , intersperseSuffix
209209 -- , intersperseBySpan
210− , interject
210+ , interjectSuffix
211211
212212 -- ** Reordering
213213 , reverse
@@ -220,8 +220,9 @@ module Streamly.Internal.Prelude
220220
221221 -- ** Interleaving
222222 , interleave
223− , interleaveFst
224223 , interleaveMin
224+ , interleaveSuffix
225+ , interleaveInfix
225226
226227 , Serial.wSerialFst
227228 , Serial.wSerialMin
@@ -254,8 +255,12 @@ module Streamly.Internal.Prelude
254255 , concatUnfoldRoundrobin
255256 , concatMap
256257 , concatMapWith
257− -- , intercalate
258+ , gintercalate
259+ , gintercalateSuffix
260+ , intercalate
258261 , intercalateSuffix
262+ , interpose
263+ , interposeSuffix
259264
260265 -- -- ** Breaking
261266
@@ -400,7 +405,8 @@ import Prelude
400405 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
401406 notElem, maximum, minimum, head, last, tail, length, null,
402407 reverse, iterate, init, and, or, lookup, foldr1, (!!),
403− scanl, scanl1, replicate, concatMap, span, splitAt, break)
408+ scanl, scanl1, replicate, concatMap, span, splitAt, break,
409+ repeat)
404410
405411import qualified Data.Heap as H
406412import qualified Data.Map.Strict as Map
@@ -671,6 +677,14 @@ replicateMSerial n = fromStreamS . S.replicateM n
671677replicate :: (IsStream t, Monad m) => Int -> a -> t m a
672678replicate n = fromStreamS . S.replicate n
673679
680+-- |
681+-- Generate an infinite stream by repeating a pure value.
682+--
683+-- @since 0.4.0
684+{-# INLINE_NORMAL repeat #-}
685+repeat :: (IsStream t, Monad m) => a -> t m a
686+repeat = fromStreamS . S.repeat
687+
674688-- |
675689-- @
676690-- repeatM = fix . consM
@@ -687,9 +701,14 @@ replicate n = fromStreamS . S.replicate n
687701-- /Concurrent, infinite (do not use with 'parallely')/
688702--
689703-- @since 0.2.0
704+{-# INLINE_EARLY repeatM #-}
690705repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
691−repeatM = go
692− where go m = m |: go m
706+repeatM = K.repeatM
707+
708+{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
709+{-# INLINE repeatMSerial #-}
710+repeatMSerial :: MonadAsync m => m a -> SerialT m a
711+repeatMSerial = fromStreamS . S.repeatM
693712
694713-- |
695714-- @
@@ -1831,9 +1850,9 @@ intersperse a = fromStreamS . S.intersperse a . toStreamS
18311850-- | Insert a monadic action after each element in the stream.
18321851--
18331852-- @since 0.7.0
1834−{-# INLINE insertAfterEach #-}
1835−insertAfterEach :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1836−insertAfterEach m = fromStreamD . D.insertAfterEach m . toStreamD
1853+{-# INLINE intersperseSuffix #-}
1854+intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1855+intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
18371856
18381857{-
18391858-- | Intersperse a monadic action into the input stream after every @n@
@@ -1854,16 +1873,16 @@ intersperseBySpan _n _f _xs = undefined
18541873-- seconds.
18551874--
18561875-- @
1857−-- > S.drain $ S.interject 1 (putChar ',') $ S.mapM (\\x -> threadDelay 1000000 >> putChar x) $ S.fromList "hello"
1876+-- > S.drain $ S.interjectSuffix 1 (putChar ',') $ S.mapM (\\x -> threadDelay 1000000 >> putChar x) $ S.fromList "hello"
18581877-- "h,e,l,l,o"
18591878-- @
18601879--
18611880-- @since 0.7.0
1862−{-# INLINE interject #-}
1863−interject
1881+{-# INLINE interjectSuffix #-}
1882+interjectSuffix
18641883 :: (IsStream t, MonadAsync m)
18651884 => Double -> m a -> t m a -> t m a
1866−interject n f xs = xs `Par.parallelFst` repeatM timed
1885+interjectSuffix n f xs = xs `Par.parallelFst` repeatM timed
18671886 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
18681887
18691888-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
@@ -2144,13 +2163,26 @@ concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
21442163append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
21452164append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
21462165
2147−-- Same as 'wSerial'. We should perhaps rename wSerial. If named explicitly
2148−-- this would be interleaveMax.
2166+-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
2167+-- XXX Document the interleaving behavior of side effects in all the
2168+-- interleaving combinators.
2169+-- XXX Write time-domain equivalents of these. In the time domain we can
2170+-- interleave two streams such that the value of second stream is always taken
2171+-- from its last value even if no new value is being yielded, like
2172+-- zipWithLatest. It would be something like interleaveWithLatest.
21492173--
21502174-- | Interleaves the outputs of two streams, yielding elements from each stream
21512175-- alternately, starting from the first stream. If any of the streams finishes
21522176-- early the other stream continues alone until it too finishes.
21532177--
2178+-- >>> :set -XOverloadedStrings
2179+-- >>> interleave "ab" ",,,," :: SerialT Identity Char
2180+-- fromList "a,b,,,"
2181+-- >>> interleave "abcd" ",," :: SerialT Identity Char
2182+-- fromList "a,b,cd"
2183+--
2184+-- 'interleave' is dual to 'interleaveMin', it can be called @interleaveMax@.
2185+--
21542186-- Do not use at scale in concatMapWith.
21552187--
21562188-- @since 0.7.0
@@ -2160,18 +2192,63 @@ interleave m1 m2 = fromStreamD $ D.interleave (toStreamD m1) (toStreamD m2)
21602192
21612193-- | Interleaves the outputs of two streams, yielding elements from each stream
21622194-- alternately, starting from the first stream. As soon as the first stream
2163−-- finishes the output stops discarding the second stream.
2195+-- finishes, the output stops, discarding the remaining part of the second
2196+-- stream. In this case, the last element in the resulting stream would be from
2197+-- the second stream. If the second stream finishes early then the first stream
2198+-- still continues to yield elements until it finishes.
2199+--
2200+-- >>> :set -XOverloadedStrings
2201+-- >>> interleaveSuffix "abc" ",,,," :: SerialT Identity Char
2202+-- fromList "a,b,c,"
2203+-- >>> interleaveSuffix "abc" "," :: SerialT Identity Char
2204+-- fromList "a,bc"
2205+--
2206+-- 'interleaveSuffix' is a dual of 'interleaveInfix'.
2207+--
2208+-- Do not use at scale in concatMapWith.
2209+--
2210+-- @since 0.7.0
2211+{-# INLINE interleaveSuffix #-}
2212+interleaveSuffix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2213+interleaveSuffix m1 m2 =
2214+ fromStreamD $ D.interleaveSuffix (toStreamD m1) (toStreamD m2)
2215+
2216+-- | Interleaves the outputs of two streams, yielding elements from each stream
2217+-- alternately, starting from the first stream and ending at the first stream.
2218+-- If the second stream is longer than the first, elements from the second
2219+-- stream are infixed with elements from the first stream. If the first stream
2220+-- is longer then it continues yielding elements even after the second stream
2221+-- has finished.
2222+--
2223+-- >>> :set -XOverloadedStrings
2224+-- >>> interleaveInfix "abc" ",,,," :: SerialT Identity Char
2225+-- fromList "a,b,c"
2226+-- >>> interleaveInfix "abc" "," :: SerialT Identity Char
2227+-- fromList "a,bc"
2228+--
2229+-- 'interleaveInfix' is a dual of 'interleaveSuffix'.
21642230--
21652231-- Do not use at scale in concatMapWith.
21662232--
21672233-- @since 0.7.0
2168−{-# INLINE interleaveFst #-}
2169−interleaveFst ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2170−interleaveFst m1 m2 = fromStreamD $ D.interleaveFst (toStreamD m1) (toStreamD m2)
2234+{-# INLINE interleaveInfix #-}
2235+interleaveInfix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2236+interleaveInfix m1 m2 =
2237+ fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
21712238
21722239-- | Interleaves the outputs of two streams, yielding elements from each stream
21732240-- alternately, starting from the first stream. The output stops as soon as any
2174−-- of the two streams finishes discarding the other.
2241+-- of the two streams finishes, discarding the remaining part of the other
2242+-- stream. The last element of the resulting stream would be from the longer
2243+-- stream.
2244+--
2245+-- >>> :set -XOverloadedStrings
2246+-- >>> interleaveMin "ab" ",,,," :: SerialT Identity Char
2247+-- fromList "a,b,"
2248+-- >>> interleaveMin "abcd" ",," :: SerialT Identity Char
2249+-- fromList "a,b,c"
2250+--
2251+-- 'interleaveMin' is dual to 'interleave'.
21752252--
21762253-- Do not use at scale in concatMapWith.
21772254--
@@ -2235,29 +2312,103 @@ concatUnfoldRoundrobin ::(IsStream t, Monad m)
22352312concatUnfoldRoundrobin u m =
22362313 fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
22372314
2238−{-
2239−-- | Insert a stream between segements of streams and flatten.
2240−intercalate :: (IsStream t, MonadAsync m)
2241− => SerialT Identity b -> (a -> t m b) -> t m a -> t m b
2242−intercalate = undefined
2243−-}
2315+-- XXX we can swap the order of arguments to gintercalate so that the
2316+-- definition of concatUnfold becomes simpler? The first stream should be
2317+-- infixed inside the second one. However, if we change the order in
2318+-- "interleave" as well similarly, then that will make it a bit unintuitive.
2319+--
2320+-- > concatUnfold unf str =
2321+-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
2322+--
2323+-- | 'interleaveInfix' followed by unfold and concat.
2324+--
2325+-- /Internal/
2326+{-# INLINE gintercalate #-}
2327+gintercalate
2328+ :: (IsStream t, Monad m)
2329+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
2330+gintercalate unf1 str1 unf2 str2 =
2331+ D.fromStreamD $ D.gintercalate
2332+ unf1 (D.toStreamD str1)
2333+ unf2 (D.toStreamD str2)
22442334
2245−-- | @intercalateSuffix genSuffix seed gen stream@ generates streams from seeds
2246−-- in the input @stream@ using the generator @gen@ and concatenates them
2247−-- after suffixing the stream generated by @genSuffix@ using @seed@.
2335+-- XXX The order of arguments in "intercalate" is consistent with the list
2336+-- intercalate but inconsistent with gintercalate and other stream interleaving
2337+-- combinators. We can change the order of the arguments in other combinators
2338+-- but then 'interleave' combinator may become a bit unintuitive because we
2339+-- will be starting with the second stream.
2340+
2341+-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
2342+-- > intercalate a unf str = concatUnfold unf $ intersperse a str
22482343--
2249−-- For example to insert CRLF in a stream of character strings:
2344+-- | 'intersperse' followed by unfold and concat.
22502345--
2251−-- > unlines = intercalateSuffix UF.fromList "\r\n" UF.fromList
2346+-- > unwords = intercalate " " UF.fromList
22522347--
2253−{-# INLINE intercalateSuffix #-}
2254−intercalateSuffix
2348+-- >>> intercalate " " UF.fromList ["abc", "def", "ghi"]
2349+-- > "abc def ghi"
2350+--
2351+{-# INLINE intercalate #-}
2352+intercalate :: (IsStream t, Monad m)
2353+ => b -> Unfold m b c -> t m b -> t m c
2354+intercalate seed unf str = D.fromStreamD $
2355+ D.concatMapU unf $ D.intersperse seed (toStreamD str)
2356+
2357+-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
2358+--
2359+-- | Unfold the elements of a stream, intersperse the given element between the
2360+-- unfolded streams and then concat them into a single stream.
2361+--
2362+-- > unwords = S.interpose ' '
2363+--
2364+-- /Internal/
2365+{-# INLINE interpose #-}
2366+interpose :: (IsStream t, Monad m)
2367+ => c -> Unfold m b c -> t m b -> t m c
2368+interpose x unf str =
2369+ D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
2370+
2371+-- | 'interleaveSuffix' followed by unfold and concat.
2372+--
2373+-- /Internal/
2374+{-# INLINE gintercalateSuffix #-}
2375+gintercalateSuffix
22552376 :: (IsStream t, Monad m)
2256− => Unfold m a c -> a -> Unfold m b c -> t m b -> t m c
2257−intercalateSuffix suffix seed unf str =
2258− D.fromStreamD $ D.interleaveFstThenConcat
2259− unf (D.toStreamD str)
2260− suffix (D.repeat seed)
2377+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
2378+gintercalateSuffix unf1 str1 unf2 str2 =
2379+ D.fromStreamD $ D.gintercalateSuffix
2380+ unf1 (D.toStreamD str1)
2381+ unf2 (D.toStreamD str2)
2382+
2383+-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
2384+-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
2385+--
2386+-- | 'intersperseSuffix' followed by unfold and concat.
2387+--
2388+-- > unlines = intercalateSuffix "\n" UF.fromList
2389+--
2390+-- >>> intercalate "\n" UF.fromList ["abc", "def", "ghi"]
2391+-- > "abc\ndef\nghi\n"
2392+--
2393+{-# INLINE intercalateSuffix #-}
2394+intercalateSuffix :: (IsStream t, Monad m)
2395+ => b -> Unfold m b c -> t m b -> t m c
2396+intercalateSuffix seed unf str = fromStreamD $ D.concatMapU unf
2397+ $ D.intersperseSuffix (return seed) (D.toStreamD str)
2398+
2399+-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
2400+--
2401+-- | Unfold the elements of a stream, append the given element after each
2402+-- unfolded stream and then concat them into a single stream.
2403+--
2404+-- > unlines = S.interposeSuffix '\n'
2405+--
2406+-- /Internal/
2407+{-# INLINE interposeSuffix #-}
2408+interposeSuffix :: (IsStream t, Monad m)
2409+ => c -> Unfold m b c -> t m b -> t m c
2410+interposeSuffix x unf str =
2411+ D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
22612412
22622413------------------------------------------------------------------------------
22632414-- Grouping/Splitting
@@ -2407,7 +2558,7 @@ intervalsOf
24072558 => Double -> Fold m a b -> t m a -> t m b
24082559intervalsOf n f xs =
24092560 splitWithSuffix isNothing (FL.lcatMaybes f)
2410− (interject n (return Nothing) (Serial.map Just xs))
2561+ (interjectSuffix n (return Nothing) (Serial.map Just xs))
24112562
24122563------------------------------------------------------------------------------
24132564-- Element Aware APIs