Rename concatUnfold to unfoldMany #986

This commit is contained in:
Ranjeet Kumar Ranjan 2021-03-20 10:53:50 +05:30 committed by Harendra Kumar
parent 7759cc0082
commit b73b5ffa3a
24 changed files with 125 additions and 118 deletions

View File

@ -402,20 +402,20 @@ inspect $ hasNoTypeClasses 'concatMapRepl
inspect $ 'concatMapRepl `hasNoType` ''SPEC
#endif
-- concatUnfold replicate/unfoldrM
-- unfoldMany replicate/unfoldrM
{-# INLINE concatUnfoldRepl #-}
concatUnfoldRepl :: Int -> Int -> Int -> IO ()
concatUnfoldRepl outer inner n =
{-# INLINE unfoldManyRepl #-}
unfoldManyRepl :: Int -> Int -> Int -> IO ()
unfoldManyRepl outer inner n =
S.drain
$ S.concatUnfold
$ S.unfoldMany
(UF.lmap return (UF.replicateM inner))
(sourceUnfoldrMN outer n)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'concatUnfoldRepl
inspect $ 'concatUnfoldRepl `hasNoType` ''S.ConcatMapUState
inspect $ 'concatUnfoldRepl `hasNoType` ''SPEC
inspect $ hasNoTypeClasses 'unfoldManyRepl
inspect $ 'unfoldManyRepl `hasNoType` ''S.ConcatMapUState
inspect $ 'unfoldManyRepl `hasNoType` ''SPEC
#endif
-------------------------------------------------------------------------------
@ -488,11 +488,11 @@ o_1_space =
, benchIOSrc1 "concatMap (1 of n)"
(concatMap 1 value)
-- concatMap vs concatUnfold
-- concatMap vs unfoldMany
, benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
(concatMapRepl value2 value2)
, benchIOSrc1 "concatUnfoldRepl (sqrt n of sqrt n)"
(concatUnfoldRepl value2 value2)
, benchIOSrc1 "unfoldManyRepl (sqrt n of sqrt n)"
(unfoldManyRepl value2 value2)
]
, bgroup "filtering"
[ benchFold "filter-even" (filterEven 1) sourceUnfoldrM

View File

@ -286,7 +286,7 @@ toChunksConcatUnfoldCountLines inh =
$ IUS.lines FL.drain
$ SS.decodeLatin1
-- XXX replace with toBytes
$ S.concatUnfold A.read (IFH.toChunks inh)
$ S.unfoldMany A.read (IFH.toChunks inh)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'toChunksConcatUnfoldCountLines

View File

@ -261,22 +261,22 @@ inspect $ hasNoTypeClasses 'concatMapWithAppend
inspect $ 'concatMapWithAppend `hasNoType` ''SPEC
#endif
-- concatUnfold
-- unfoldMany
-- concatUnfold replicate/unfoldrM
-- unfoldMany replicate/unfoldrM
{-# INLINE concatUnfoldRepl #-}
concatUnfoldRepl :: Int -> Int -> Int -> IO ()
concatUnfoldRepl outer inner n =
{-# INLINE unfoldManyRepl #-}
unfoldManyRepl :: Int -> Int -> Int -> IO ()
unfoldManyRepl outer inner n =
S.drain
$ S.concatUnfold
$ S.unfoldMany
(UF.lmap return (UF.replicateM inner))
(sourceUnfoldrM outer n)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'concatUnfoldRepl
inspect $ 'concatUnfoldRepl `hasNoType` ''D.ConcatMapUState
inspect $ 'concatUnfoldRepl `hasNoType` ''SPEC
inspect $ hasNoTypeClasses 'unfoldManyRepl
inspect $ 'unfoldManyRepl `hasNoType` ''D.ConcatMapUState
inspect $ 'unfoldManyRepl `hasNoType` ''SPEC
#endif
o_1_space_concat :: Int -> [Benchmark]
@ -322,11 +322,11 @@ o_1_space_concat value = sqrtVal `seq`
, benchIOSrc1 "concatMapWithAppend (2 of n/2)"
(concatMapWithAppend 2 (value `div` 2))
-- concatMap vs concatUnfold
-- concatMap vs unfoldMany
, benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
(concatMapRepl sqrtVal sqrtVal)
, benchIOSrc1 "concatUnfoldRepl (sqrt n of sqrt n)"
(concatUnfoldRepl sqrtVal sqrtVal)
, benchIOSrc1 "unfoldManyRepl (sqrt n of sqrt n)"
(unfoldManyRepl sqrtVal sqrtVal)
]
]

View File

@ -122,31 +122,31 @@ o_1_space_concat value =
]
]
{-# INLINE concatUnfoldInterleaveRepl4xN #-}
concatUnfoldInterleaveRepl4xN :: Int -> Int -> IO ()
concatUnfoldInterleaveRepl4xN value n =
S.drain $ Internal.concatUnfoldInterleave
{-# INLINE unfoldManyInterleaveRepl4xN #-}
unfoldManyInterleaveRepl4xN :: Int -> Int -> IO ()
unfoldManyInterleaveRepl4xN value n =
S.drain $ Internal.unfoldManyInterleave
(UF.lmap return (UF.replicateM 4))
(sourceUnfoldrM (value `div` 4) n)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'concatUnfoldInterleaveRepl4xN
-- inspect $ 'concatUnfoldInterleaveRepl4xN `hasNoType` ''SPEC
-- inspect $ 'concatUnfoldInterleaveRepl4xN `hasNoType`
inspect $ hasNoTypeClasses 'unfoldManyInterleaveRepl4xN
-- inspect $ 'unfoldManyInterleaveRepl4xN `hasNoType` ''SPEC
-- inspect $ 'unfoldManyInterleaveRepl4xN `hasNoType`
-- ''D.ConcatUnfoldInterleaveState
#endif
{-# INLINE concatUnfoldRoundrobinRepl4xN #-}
concatUnfoldRoundrobinRepl4xN :: Int -> Int -> IO ()
concatUnfoldRoundrobinRepl4xN value n =
S.drain $ Internal.concatUnfoldRoundrobin
{-# INLINE unfoldManyRoundRobinRepl4xN #-}
unfoldManyRoundRobinRepl4xN :: Int -> Int -> IO ()
unfoldManyRoundRobinRepl4xN value n =
S.drain $ Internal.unfoldManyRoundRobin
(UF.lmap return (UF.replicateM 4))
(sourceUnfoldrM (value `div` 4) n)
#ifdef INSPECTION
inspect $ hasNoTypeClasses 'concatUnfoldRoundrobinRepl4xN
-- inspect $ 'concatUnfoldRoundrobinRepl4xN `hasNoType` ''SPEC
-- inspect $ 'concatUnfoldRoundrobinRepl4xN `hasNoType`
inspect $ hasNoTypeClasses 'unfoldManyRoundRobinRepl4xN
-- inspect $ 'unfoldManyRoundRobinRepl4xN `hasNoType` ''SPEC
-- inspect $ 'unfoldManyRoundRobinRepl4xN `hasNoType`
-- ''D.ConcatUnfoldInterleaveState
#endif
@ -159,11 +159,11 @@ o_n_heap_concat value =
-- WSerial expands slowly because of binary interleave behavior and
-- this expands immediately because of Nary interleave behavior.
benchIOSrc1
"concatUnfoldInterleaveRepl (x/4,4)"
(concatUnfoldInterleaveRepl4xN value)
"unfoldManyInterleaveRepl (x/4,4)"
(unfoldManyInterleaveRepl4xN value)
, benchIOSrc1
"concatUnfoldRoundrobinRepl (x/4,4)"
(concatUnfoldRoundrobinRepl4xN value)
"unfoldManyRoundRobinRepl (x/4,4)"
(unfoldManyRoundRobinRepl4xN value)
]
]

View File

@ -52,7 +52,7 @@ The haddock documentation includes a note when an operation cannot fuse.
### Unfolds
* Use unfolds especially when higher order operations are involved. For
example, `concatUnfold` can fuse completely whereas `concatMap` would
example, `unfoldMany` can fuse completely whereas `concatMap` would
not fuse.
* Use `outerProduct` in `Unfold` module instead of using the monad instance of
streams to fuse nested loops where performance matters. See the unfold

View File

@ -167,7 +167,7 @@ we can resolve this using fusion-plugin in future.
### Delayed INLINE
When a function is passed to a higher order function e.g. a function
passed to `concatMap` or `concatUnfold` then we want the function to be
passed to `concatMap` or `unfoldMany` then we want the function to be
inlined after the higher order is inlined so that proper fusion of the
higher order function can occur. For such cases we usually add INLINE[1]
on the function being passed to instruct GHC not to inline it too early.

View File

@ -30,7 +30,7 @@
-- much less efficient when compared to combinators using 'Unfold'. For
-- example, the 'Streamly.Prelude.concatMap' combinator which uses @a -> t m b@
-- (where @t@ is a stream type) to generate streams is much less efficient
-- compared to 'Streamly.Prelude.concatUnfold'.
-- compared to 'Streamly.Prelude.unfoldMany'.
--
-- On the other hand, transformation operations on stream types are as
-- efficient as transformations on 'Unfold'.

View File

@ -569,7 +569,7 @@ data FlattenState s a =
-- | Use the "read" unfold instead.
--
-- @flattenArrays = concatUnfold read@
-- @flattenArrays = unfoldMany read@
--
-- We can try this if there are any fusion issues in the unfold.
--
@ -603,7 +603,7 @@ flattenArrays (D.Stream step state) = D.Stream step' (OuterLoop state)
-- | Use the "readRev" unfold instead.
--
-- @flattenArrays = concatUnfold readRev@
-- @flattenArrays = unfoldMany readRev@
--
-- We can try this if there are any fusion issues in the unfold.
--
@ -987,7 +987,7 @@ fromStreamD :: (MonadIO m, Storable a) => D.Stream m a -> m (Array a)
fromStreamD m = do
buffered <- bufferChunks m
len <- K.foldl' (+) 0 (K.map length buffered)
fromStreamDN len $ D.concatUnfold read $ D.fromStreamK buffered
fromStreamDN len $ D.unfoldMany read $ D.fromStreamK buffered
-- | Create an 'Array' from a list. The list must be of finite size.
--

View File

@ -334,7 +334,7 @@ arraysOf n str = D.map unsafeFreeze $ MA.arraysOf n str
-- | Use the "read" unfold instead.
--
-- @flattenArrays = concatUnfold read@
-- @flattenArrays = unfoldMany read@
--
-- We can try this if there are any fusion issues in the unfold.
--
@ -345,7 +345,7 @@ flattenArrays = MA.flattenArrays . D.map unsafeThaw
-- | Use the "readRev" unfold instead.
--
-- @flattenArrays = concatUnfold readRev@
-- @flattenArrays = unfoldMany readRev@
--
-- We can try this if there are any fusion issues in the unfold.
--

View File

@ -173,7 +173,7 @@ last arr = readIndex arr (length arr - 1)
concat :: (IsStream t, MonadIO m, Prim a) => t m (Array a) -> t m a
-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
concat m = D.fromStreamD $ D.concatUnfold read (D.toStreamD m)
concat m = D.fromStreamD $ D.unfoldMany read (D.toStreamD m)
-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
-- maximum specified size in bytes.

View File

@ -93,19 +93,19 @@ arraysOf n str = D.fromStreamD $ A.arraysOf n (D.toStreamD str)
--
-- Same as the following but more efficient:
--
-- > concat = Stream.concatUnfold Array.read
-- > concat = Stream.unfoldMany Array.read
--
-- @since 0.7.0
{-# INLINE concat #-}
concat :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
concat m = D.fromStreamD $ D.concatUnfold A.read (D.toStreamD m)
concat m = D.fromStreamD $ D.unfoldMany A.read (D.toStreamD m)
-- | Convert a stream of arrays into a stream of their elements reversing the
-- contents of each array before flattening.
--
-- > concatRev = Stream.concatUnfold Array.readRev
-- > concatRev = Stream.unfoldMany Array.readRev
--
-- @since 0.7.0
{-# INLINE concatRev #-}

View File

@ -460,7 +460,7 @@ concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
-- concatMap f = 'concatMapM' (return . f)
-- concatMap = 'concatMapWith' 'Serial.serial'
-- concatMap f = 'concat . map f'
-- concatMap f = 'concatUnfold' (UF.lmap f UF.fromStream)
-- concatMap f = 'unfoldMany' (UF.lmap f UF.fromStream)
-- @
--
-- @since 0.6.0

View File

@ -89,12 +89,13 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
-- ** Append Many (Unfold)
-- | Unfold and flatten streams.
, unfoldMany
, unfoldManyInterleave
, unfoldManyRoundRobin
, concatUnfold
, concatUnfoldInterleave
, concatUnfoldRoundrobin
-- ** Interpose
-- | Insert effects between streams. Like concatUnfold but intersperses an
-- | Insert effects between streams. Like unfoldMany but intersperses an
-- effect between the streams. A special case of gintercalate.
, interpose
, interposeSuffix
@ -102,7 +103,7 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
-- ** Intercalate
-- | Insert Streams between Streams.
-- Like concatUnfold but intersperses streams from another source between
-- Like unfoldMany but intersperses streams from another source between
-- the streams from the first source.
, intercalate
, intercalateSuffix
@ -449,40 +450,45 @@ mergeAsyncByM f m1 m2 =
let par = Par.mkParallelD . toStreamD
in D.mergeByM f (par m1) (par m2)
-- @since 0.7.0
{-# DEPRECATED concatUnfold "Please use unfoldMany instead." #-}
{-# INLINE concatUnfold #-}
concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
concatUnfold u m = fromStreamD $ D.unfoldMany u (toStreamD m)
------------------------------------------------------------------------------
-- Combine N Streams - concatUnfold
-- Combine N Streams - unfoldMany
------------------------------------------------------------------------------
-- XXX Rename to unfoldMany
--
-- | Like 'concatMap' but uses an 'Unfold' for stream generation. Unlike
-- 'concatMap' this can fuse the 'Unfold' code with the inner loop and
-- therefore provide many times better performance.
--
-- @since 0.7.0
{-# INLINE concatUnfold #-}
concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
concatUnfold u m = fromStreamD $ D.concatUnfold u (toStreamD m)
-- @since 0.8.0
{-# INLINE unfoldMany #-}
unfoldMany ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
unfoldMany u m = fromStreamD $ D.unfoldMany u (toStreamD m)
-- | Like 'concatUnfold' but interleaves the streams in the same way as
-- | Like 'unfoldMany' but interleaves the streams in the same way as
-- 'interleave' behaves instead of appending them.
--
-- /Pre-release/
{-# INLINE concatUnfoldInterleave #-}
concatUnfoldInterleave ::(IsStream t, Monad m)
{-# INLINE unfoldManyInterleave #-}
unfoldManyInterleave ::(IsStream t, Monad m)
=> Unfold m a b -> t m a -> t m b
concatUnfoldInterleave u m =
fromStreamD $ D.concatUnfoldInterleave u (toStreamD m)
unfoldManyInterleave u m =
fromStreamD $ D.unfoldManyInterleave u (toStreamD m)
-- | Like 'concatUnfold' but executes the streams in the same way as
-- | Like 'unfoldMany' but executes the streams in the same way as
-- 'roundrobin'.
--
-- /Pre-release/
{-# INLINE concatUnfoldRoundrobin #-}
concatUnfoldRoundrobin ::(IsStream t, Monad m)
{-# INLINE unfoldManyRoundRobin #-}
unfoldManyRoundRobin ::(IsStream t, Monad m)
=> Unfold m a b -> t m a -> t m b
concatUnfoldRoundrobin u m =
fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
unfoldManyRoundRobin u m =
fromStreamD $ D.unfoldManyRoundRobin u (toStreamD m)
------------------------------------------------------------------------------
-- Combine N Streams - interpose
@ -521,11 +527,11 @@ interposeSuffix x unf str =
------------------------------------------------------------------------------
-- XXX we can swap the order of arguments to gintercalate so that the
-- definition of concatUnfold becomes simpler? The first stream should be
-- definition of unfoldMany becomes simpler? The first stream should be
-- infixed inside the second one. However, if we change the order in
-- "interleave" as well similarly, then that will make it a bit unintuitive.
--
-- > concatUnfold unf str =
-- > unfoldMany unf str =
-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
--
-- | 'interleaveInfix' followed by unfold and concat.
@ -547,7 +553,7 @@ gintercalate unf1 str1 unf2 str2 =
-- will be starting with the second stream.
-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
-- > intercalate a unf str = concatUnfold unf $ intersperse a str
-- > intercalate a unf str = unfoldMany unf $ intersperse a str
--
-- | 'intersperse' followed by unfold and concat.
--
@ -561,7 +567,7 @@ gintercalate unf1 str1 unf2 str2 =
intercalate :: (IsStream t, Monad m)
=> b -> Unfold m b c -> t m b -> t m c
intercalate seed unf str = D.fromStreamD $
D.concatUnfold unf $ D.intersperse seed (toStreamD str)
D.unfoldMany unf $ D.intersperse seed (toStreamD str)
-- | 'interleaveSuffix' followed by unfold and concat.
--
@ -576,7 +582,7 @@ gintercalateSuffix unf1 str1 unf2 str2 =
unf2 (D.toStreamD str2)
-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
-- > intercalateSuffix a unf str = unfoldMany unf $ intersperseSuffix a str
--
-- | 'intersperseSuffix' followed by unfold and concat.
--
@ -589,7 +595,7 @@ gintercalateSuffix unf1 str1 unf2 str2 =
{-# INLINE intercalateSuffix #-}
intercalateSuffix :: (IsStream t, Monad m)
=> b -> Unfold m b c -> t m b -> t m c
intercalateSuffix seed unf str = fromStreamD $ D.concatUnfold unf
intercalateSuffix seed unf str = fromStreamD $ D.unfoldMany unf
$ D.intersperseSuffix (return seed) (D.toStreamD str)
{-

View File

@ -10,7 +10,7 @@
-- Prefer unfolds ("Streamly.Internal.Data.Unfold") over the combinators in
-- this module. They are more powerful and efficient as they can be transformed
-- and composed on the input side efficiently and they can fuse in nested
-- operations (e.g. concatUnfold). All the combinators in this module can be
-- operations (e.g. unfoldMany). All the combinators in this module can be
-- expressed using unfolds with the same efficiency.
--
-- Operations in this module that are not in "Streamly.Internal.Data.Unfold":

View File

@ -35,13 +35,13 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
-- *** Appending
-- | Append a stream after another. A special case of concatMap or
-- concatUnfold.
-- unfoldMany.
AppendState(..)
, append
-- *** Interleaving
-- | Interleave elements from two streams alternately. A special case of
-- concatUnfoldInterleave.
-- unfoldManyInterleave.
, InterleaveState(..)
, interleave
, interleaveMin
@ -51,7 +51,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
-- *** Scheduling
-- | Execute streams alternately irrespective of whether they generate
-- elements or not. Note 'interleave' would execute a stream until it
-- yields an element. A special case of concatUnfoldRoundrobin.
-- yields an element. A special case of unfoldManyRoundRobin.
, roundRobin -- interleaveFair?/ParallelFair
-- *** Zipping
@ -70,7 +70,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
-- @
-- concat: f (t m a) -> t m a
-- concatMap: (a -> t m b) -> t m a -> t m b
-- concatUnfold: Unfold m a b -> t m a -> t m b
-- unfoldMany: Unfold m a b -> t m a -> t m b
-- @
-- *** ConcatMap
@ -83,19 +83,19 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
-- | Generate streams by using an unfold on each element of an input
-- stream, append the resulting streams and flatten. A special case of
-- gintercalate.
, concatUnfold
, unfoldMany
, ConcatUnfoldInterleaveState (..)
, concatUnfoldInterleave
, concatUnfoldRoundrobin
, unfoldManyInterleave
, unfoldManyRoundRobin
-- *** Interpose
-- | Like concatUnfold but intersperses an effect between the streams. A
-- | Like unfoldMany but intersperses an effect between the streams. A
-- special case of gintercalate.
, interpose
, interposeSuffix
-- *** Intercalate
-- | Like concatUnfold but intersperses streams from another source between
-- | Like unfoldMany but intersperses streams from another source between
-- the streams from the first source.
, gintercalate
, gintercalateSuffix
@ -116,7 +116,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
-- ** Parsing
-- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
-- concatUnfold. concatMap generates a stream from single values in a
-- unfoldMany. concatMap generates a stream from single values in a
-- stream and flattens, parseMany does the opposite of flattening by
-- splitting the stream and then folds each such split to single value in
-- the output stream.
@ -477,7 +477,7 @@ mergeBy
mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
------------------------------------------------------------------------------
-- Combine N Streams - concatUnfold
-- Combine N Streams - unfoldMany
------------------------------------------------------------------------------
data ConcatUnfoldInterleaveState o i =
@ -502,9 +502,9 @@ data ConcatUnfoldInterleaveState o i =
-- Ideally, we need some scheduling bias to inner streams vs outer stream.
-- Maybe we can configure the behavior.
--
{-# INLINE_NORMAL concatUnfoldInterleave #-}
concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
{-# INLINE_NORMAL unfoldManyInterleave #-}
unfoldManyInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
unfoldManyInterleave (Unfold istep inject) (Stream ostep ost) =
Stream step (ConcatUnfoldInterleaveOuter ost [])
where
{-# INLINE_LATE step #-}
@ -553,11 +553,11 @@ concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
--
-- This could be inefficient if the tasks are too small.
--
-- Compared to concatUnfoldInterleave this one switches streams on Skips.
-- Compared to unfoldManyInterleave this one switches streams on Skips.
--
{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
{-# INLINE_NORMAL unfoldManyRoundRobin #-}
unfoldManyRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
unfoldManyRoundRobin (Unfold istep inject) (Stream ostep ost) =
Stream step (ConcatUnfoldInterleaveOuter ost [])
where
{-# INLINE_LATE step #-}

View File

@ -1129,7 +1129,7 @@ reverse' m = Stream step Nothing
return $ Yield x (Just (start, next))
-}
reverse' =
A.flattenArraysRev -- concatUnfold A.readRev
A.flattenArraysRev -- unfoldMany A.readRev
. fromStreamK
. K.reverse
. toStreamK

View File

@ -75,7 +75,7 @@ module Streamly.Internal.Data.Stream.StreamD.Type
-- * Nesting
, ConcatMapUState (..)
, concatUnfold
, unfoldMany
, concatMap
, concatMapM
, FoldMany (..) -- for inspection testing
@ -690,7 +690,7 @@ instance Applicative f => Applicative (Stream f) where
(<*) = apDiscardSnd
------------------------------------------------------------------------------
-- Combine N Streams - concatUnfold
-- Combine N Streams - unfoldMany
------------------------------------------------------------------------------
-- Define a unique structure to use in inspection testing
@ -698,7 +698,7 @@ data ConcatMapUState o i =
ConcatMapUOuter o
| ConcatMapUInner o i
-- | @concatUnfold unfold stream@ uses @unfold@ to map the input stream elements
-- | @unfoldMany unfold stream@ uses @unfold@ to map the input stream elements
-- to streams and then flattens the generated streams into a single output
-- stream.
@ -707,9 +707,9 @@ data ConcatMapUState o i =
-- optimization via fusion. This can be many times more efficient than
-- 'concatMap'.
{-# INLINE_NORMAL concatUnfold #-}
concatUnfold :: Monad m => Unfold m a b -> Stream m a -> Stream m b
concatUnfold (Unfold istep inject) (Stream ostep ost) =
{-# INLINE_NORMAL unfoldMany #-}
unfoldMany :: Monad m => Unfold m a b -> Stream m a -> Stream m b
unfoldMany (Unfold istep inject) (Stream ostep ost) =
Stream step (ConcatMapUOuter ost)
where
{-# INLINE_LATE step #-}
@ -728,7 +728,7 @@ concatUnfold (Unfold istep inject) (Stream ostep ost) =
Yield x i' -> Yield x (ConcatMapUInner o i')
Skip i' -> Skip (ConcatMapUInner o i')
Stop -> Skip (ConcatMapUOuter o)
------------------------------------------------------------------------------
-- Combine N Streams - concatMap
------------------------------------------------------------------------------

View File

@ -1181,7 +1181,7 @@ instance Monad m => Monad (Stream m) where
{-
-- Like concatMap but generates stream using an unfold function. Similar to
-- concatUnfold but for StreamK.
-- unfoldMany but for StreamK.
concatUnfoldr :: IsStream t
=> (b -> t m (Maybe (a, b))) -> t m b -> t m a
concatUnfoldr = undefined

View File

@ -17,13 +17,13 @@
--
-- This allows an important optimization to occur in several cases, making the
-- 'Unfold' a more efficient abstraction. Consider the 'concatMap' and
-- 'concatUnfold' operations, the latter is more efficient. 'concatMap'
-- 'unfoldMany' operations, the latter is more efficient. 'concatMap'
-- generates a new stream object from each element in the stream by applying
-- the supplied function to the element, the stream object includes the "step"
-- function as well as the initial "state" of the stream. Since the stream is
-- generated dynamically the compiler does not know the step function or the
-- state type statically at compile time, therefore, it cannot inline it. On
-- the other hand in case of 'concatUnfold' the compiler has visibility into
-- the other hand in case of 'unfoldMany' the compiler has visibility into
-- the unfold's state generation function, therefore, the compiler knows all
-- the types statically and it can inline the inject as well as the step
-- functions, generating efficient code. Essentially, the stream is not opaque
@ -844,7 +844,7 @@ fromProducer = Unfold step (return . FromSVarRead)
-- stream.
--
-- @
-- S.mapM_ print $ S.concatUnfold (UF.teeZipWith (,) UF.identity (UF.singleton sqrt)) $ S.fromList [1..10]
-- S.mapM_ print $ S.unfoldMany (UF.teeZipWith (,) UF.identity (UF.singleton sqrt)) $ S.fromList [1..10]
-- @
--
-- /Pre-release/

View File

@ -352,7 +352,7 @@ zipWithM f (Unfold step1 inject1) (Unfold step2 inject2) = Unfold step inject
--
-- @
-- S.mapM_ print
-- $ S.concatUnfold (UF.zipWith (,) UF.identity (UF.singleton sqrt))
-- $ S.unfoldMany (UF.zipWith (,) UF.identity (UF.singleton sqrt))
-- $ S.map (\x -> (x,x))
-- $ S.fromList [1..10]
-- @

View File

@ -596,6 +596,7 @@ module Streamly.Prelude
, concatMap
, concatMapM
, concatUnfold
, unfoldMany
-- ** Folding Containers of Streams
-- | These are variants of standard 'Foldable' fold functions that use a

View File

@ -163,7 +163,7 @@ testArraysOf =
monadicIO $ do
xs <- run
$ S.toList
$ S.concatUnfold A.read
$ S.unfoldMany A.read
$ arraysOf 240
$ S.fromList list
assert (xs == list)

View File

@ -630,7 +630,7 @@ parseUnfold = do
Producer.simplify (Source.parseManyD parser readSrc)
xs <- run
$ S.toList
$ S.concatUnfold Unfold.fromList
$ S.unfoldMany Unfold.fromList
$ S.unfold streamParser src
listEquals (==) xs ls

View File

@ -1198,10 +1198,10 @@ transformCombineOpsCommon constr desc eq t = do
forAll (choose (0, 100)) $ \n ->
transform (concatMap (const [1..n]))
t (S.concatMapM (const (return $ S.fromList [1..n])))
prop (desc <> " concatUnfold") $
prop (desc <> " unfoldMany") $
forAll (choose (0, 100)) $ \n ->
transform (concatMap (const [1..n]))
t (S.concatUnfold (UF.lmap (const undefined)
t (S.unfoldMany (UF.lmap (const undefined)
$ UF.supply UF.fromList [1..n]))
toListFL :: Monad m => FL.Fold m a [a]