@@ -33,7 +33,7 @@ module Streamly.Internal.Prelude
33 -- ** From Values
33 -- ** From Values
36− , K.repeat
36+ , repeat
38 , replicate
38 , replicate
39 , replicateM
39 , replicateM
@@ -205,9 +205,9 @@ module Streamly.Internal.Prelude
205 , insertBy
205 , insertBy
206 , intersperseM
206 , intersperseM
207 , intersperse
207 , intersperse
208− , insertAfterEach
208+ , intersperseSuffix
209 -- , intersperseBySpan
209 -- , intersperseBySpan
210− , interject
210+ , interjectSuffix
212 -- ** Reordering
212 -- ** Reordering
213 , reverse
213 , reverse
@@ -220,8 +220,9 @@ module Streamly.Internal.Prelude
221 -- ** Interleaving
221 -- ** Interleaving
222 , interleave
222 , interleave
224 , interleaveMin
223 , interleaveMin
226 , Serial.wSerialFst
227 , Serial.wSerialFst
227 , Serial.wSerialMin
228 , Serial.wSerialMin
@@ -254,8 +255,12 @@ module Streamly.Internal.Prelude
254 , concatUnfoldRoundrobin
255 , concatUnfoldRoundrobin
255 , concatMap
256 , concatMap
256 , concatMapWith
257 , concatMapWith
259+ , gintercalateSuffix
257− -- , intercalate
260+ , intercalate
258 , intercalateSuffix
261 , intercalateSuffix
260 -- -- ** Breaking
265 -- -- ** Breaking
@@ -400,7 +405,8 @@ import Prelude
400 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
405 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
401 notElem, maximum, minimum, head, last, tail, length, null,
406 notElem, maximum, minimum, head, last, tail, length, null,
402 reverse, iterate, init, and, or, lookup, foldr1, (!!),
407 reverse, iterate, init, and, or, lookup, foldr1, (!!),
403− scanl, scanl1, replicate, concatMap, span, splitAt, break)
408+ scanl, scanl1, replicate, concatMap, span, splitAt, break,
405import qualified Data.Heap as H
411import qualified Data.Heap as H
406import qualified Data.Map.Strict as Map
412import qualified Data.Map.Strict as Map
@@ -671,6 +677,14 @@ replicateMSerial n = fromStreamS . S.replicateM n
671replicate :: (IsStream t, Monad m) => Int -> a -> t m a
677replicate :: (IsStream t, Monad m) => Int -> a -> t m a
672replicate n = fromStreamS . S.replicate n
678replicate n = fromStreamS . S.replicate n
681+-- Generate an infinite stream by repeating a pure value.
684+{-# INLINE_NORMAL repeat #-}
685+repeat :: (IsStream t, Monad m) => a -> t m a
686+repeat = fromStreamS . S.repeat
676-- repeatM = fix . consM
690-- repeatM = fix . consM
@@ -687,9 +701,14 @@ replicate n = fromStreamS . S.replicate n
687-- /Concurrent, infinite (do not use with 'parallely')/
701-- /Concurrent, infinite (do not use with 'parallely')/
689-- @since 0.2.0
703-- @since 0.2.0
704+{-# INLINE_EARLY repeatM #-}
690repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
705repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
691−repeatM = go
706+repeatM = K.repeatM
692− where go m = m |: go m
707+
708+{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
709+{-# INLINE repeatMSerial #-}
710+repeatMSerial :: MonadAsync m => m a -> SerialT m a
711+repeatMSerial = fromStreamS . S.repeatM
@@ -1831,9 +1850,9 @@ intersperse a = fromStreamS . S.intersperse a . toStreamS
1831-- | Insert a monadic action after each element in the stream.
1850-- | Insert a monadic action after each element in the stream.
1833-- @since 0.7.0
1852-- @since 0.7.0
1834−{-# INLINE insertAfterEach #-}
1853+{-# INLINE intersperseSuffix #-}
1835−insertAfterEach :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1854+intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1836−insertAfterEach m = fromStreamD . D.insertAfterEach m . toStreamD
1855+intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
1839-- | Intersperse a monadic action into the input stream after every @n@
1858-- | Intersperse a monadic action into the input stream after every @n@
@@ -1854,16 +1873,16 @@ intersperseBySpan _n _f _xs = undefined
1854-- seconds.
1873-- seconds.
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"
1858-- "h,e,l,l,o"
1877-- "h,e,l,l,o"
1861-- @since 0.7.0
1880-- @since 0.7.0
1862−{-# INLINE interject #-}
1881+{-# INLINE interjectSuffix #-}
1863−interject
1882+interjectSuffix
1864 :: (IsStream t, MonadAsync m)
1883 :: (IsStream t, MonadAsync m)
1865 => Double -> m a -> t m a -> t m a
1884 => 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
1867 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
1886 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
1869-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
1888-- | @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)
2144append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2163append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2145append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
2164append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
2147−-- Same as 'wSerial'. We should perhaps rename wSerial. If named explicitly
2166+-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
2148−-- this would be interleaveMax.
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.
2150-- | Interleaves the outputs of two streams, yielding elements from each stream
2174-- | Interleaves the outputs of two streams, yielding elements from each stream
2151-- alternately, starting from the first stream. If any of the streams finishes
2175-- alternately, starting from the first stream. If any of the streams finishes
2152-- early the other stream continues alone until it too finishes.
2176-- early the other stream continues alone until it too finishes.
2178+-- >>> :set -XOverloadedStrings
2179+-- >>> interleave "ab" ",,,," :: SerialT Identity Char
2180+-- fromList "a,b,,,"
2181+-- >>> interleave "abcd" ",," :: SerialT Identity Char
2182+-- fromList "a,b,cd"
2184+-- 'interleave' is dual to 'interleaveMin', it can be called @interleaveMax@.
2154-- Do not use at scale in concatMapWith.
2186-- Do not use at scale in concatMapWith.
2156-- @since 0.7.0
2188-- @since 0.7.0
@@ -2160,18 +2192,63 @@ interleave m1 m2 = fromStreamD $ D.interleave (toStreamD m1) (toStreamD m2)
2161-- | Interleaves the outputs of two streams, yielding elements from each stream
2193-- | Interleaves the outputs of two streams, yielding elements from each stream
2162-- alternately, starting from the first stream. As soon as the first stream
2194-- 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.
2200+-- >>> :set -XOverloadedStrings
2201+-- >>> interleaveSuffix "abc" ",,,," :: SerialT Identity Char
2202+-- fromList "a,b,c,"
2203+-- >>> interleaveSuffix "abc" "," :: SerialT Identity Char
2206+-- 'interleaveSuffix' is a dual of 'interleaveInfix'.
2208+-- Do not use at scale in concatMapWith.
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)
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
2223+-- >>> :set -XOverloadedStrings
2224+-- >>> interleaveInfix "abc" ",,,," :: SerialT Identity Char
2226+-- >>> interleaveInfix "abc" "," :: SerialT Identity Char
2229+-- 'interleaveInfix' is a dual of 'interleaveSuffix'.
2165-- Do not use at scale in concatMapWith.
2231-- Do not use at scale in concatMapWith.
2167-- @since 0.7.0
2233-- @since 0.7.0
2168−{-# INLINE interleaveFst #-}
2234+{-# INLINE interleaveInfix #-}
2169−interleaveFst ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2235+interleaveInfix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
2236+interleaveInfix m1 m2 =
2170−interleaveFst m1 m2 = fromStreamD $ D.interleaveFst (toStreamD m1) (toStreamD m2)
2237+ fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
2172-- | Interleaves the outputs of two streams, yielding elements from each stream
2239-- | Interleaves the outputs of two streams, yielding elements from each stream
2173-- alternately, starting from the first stream. The output stops as soon as any
2240-- 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
2245+-- >>> :set -XOverloadedStrings
2246+-- >>> interleaveMin "ab" ",,,," :: SerialT Identity Char
2248+-- >>> interleaveMin "abcd" ",," :: SerialT Identity Char
2251+-- 'interleaveMin' is dual to 'interleave'.
2176-- Do not use at scale in concatMapWith.
2253-- Do not use at scale in concatMapWith.
@@ -2235,29 +2312,103 @@ concatUnfoldRoundrobin ::(IsStream t, Monad m)
2235concatUnfoldRoundrobin u m =
2312concatUnfoldRoundrobin u m =
2236 fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
2313 fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
2238−{-
2315+-- XXX we can swap the order of arguments to gintercalate so that the
2239−-- | Insert a stream between segements of streams and flatten.
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.
2320+-- > concatUnfold unf str =
2321+-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
2323+-- | 'interleaveInfix' followed by unfold and concat.
2326+{-# INLINE gintercalate #-}
2240−intercalate :: (IsStream t, MonadAsync m)
2328+ :: (IsStream t, Monad m)
2241− => SerialT Identity b -> (a -> t m b) -> t m a -> t m b
2329+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
2242−intercalate = undefined
2330+gintercalate unf1 str1 unf2 str2 =
2243−-}
2331+ D.fromStreamD $ D.gintercalate
2332+ unf1 (D.toStreamD str1)
2333+ unf2 (D.toStreamD str2)
2245−-- | @intercalateSuffix genSuffix seed gen stream@ generates streams from seeds
2335+-- XXX The order of arguments in "intercalate" is consistent with the list
2246−-- in the input @stream@ using the generator @gen@ and concatenates them
2336+-- intercalate but inconsistent with gintercalate and other stream interleaving
2247−-- after suffixing the stream generated by @genSuffix@ using @seed@.
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.
2341+-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
2342+-- > intercalate a unf str = concatUnfold unf $ intersperse a str
2249−-- For example to insert CRLF in a stream of character strings:
2344+-- | 'intersperse' followed by unfold and concat.
2251−-- > unlines = intercalateSuffix UF.fromList "\r\n" UF.fromList
2346+-- > unwords = intercalate " " UF.fromList
2253−{-# INLINE intercalateSuffix #-}
2348+-- >>> intercalate " " UF.fromList ["abc", "def", "ghi"]
2254−intercalateSuffix
2349+-- > "abc def ghi"
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)
2357+-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
2359+-- | Unfold the elements of a stream, intersperse the given element between the
2360+-- unfolded streams and then concat them into a single stream.
2362+-- > unwords = S.interpose ' '
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)
2371+-- | 'interleaveSuffix' followed by unfold and concat.
2374+{-# INLINE gintercalateSuffix #-}
2255 :: (IsStream t, Monad m)
2376 :: (IsStream t, Monad m)
2256− => Unfold m a c -> a -> Unfold m b c -> t m b -> t m c
2377+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
2257−intercalateSuffix suffix seed unf str =
2378+gintercalateSuffix unf1 str1 unf2 str2 =
2258− D.fromStreamD $ D.interleaveFstThenConcat
2379+ D.fromStreamD $ D.gintercalateSuffix
2259− unf (D.toStreamD str)
2380+ unf1 (D.toStreamD str1)
2260− suffix (D.repeat seed)
2381+ unf2 (D.toStreamD str2)
2383+-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
2384+-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
2386+-- | 'intersperseSuffix' followed by unfold and concat.
2388+-- > unlines = intercalateSuffix "\n" UF.fromList
2390+-- >>> intercalate "\n" UF.fromList ["abc", "def", "ghi"]
2391+-- > "abc\ndef\nghi\n"
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)
2399+-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
2401+-- | Unfold the elements of a stream, append the given element after each
2402+-- unfolded stream and then concat them into a single stream.
2404+-- > unlines = S.interposeSuffix '\n'
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)
2262------------------------------------------------------------------------------
2413------------------------------------------------------------------------------
2263-- Grouping/Splitting
2414-- Grouping/Splitting
@@ -2407,7 +2558,7 @@ intervalsOf
2407 => Double -> Fold m a b -> t m a -> t m b
2558 => Double -> Fold m a b -> t m a -> t m b
2408intervalsOf n f xs =
2559intervalsOf n f xs =
2409 splitWithSuffix isNothing (FL.lcatMaybes f)
2560 splitWithSuffix isNothing (FL.lcatMaybes f)
2410− (interject n (return Nothing) (Serial.map Just xs))
2561+ (interjectSuffix n (return Nothing) (Serial.map Just xs))
2412------------------------------------------------------------------------------
2563------------------------------------------------------------------------------
2413-- Element Aware APIs
2564-- Element Aware APIs