@@ -63,8 +63,6 @@ module Streamly.Streams.StreamD
63 -- | Generate a monadic stream from a seed.
63 -- | Generate a monadic stream from a seed.
65 , replicate
65 , replicate
68 , replicateM
66 , replicateM
69 , fromIndices
67 , fromIndices
70 , fromIndicesM
68 , fromIndicesM
@@ -137,6 +135,7 @@ module Streamly.Streams.StreamD
137 -- ** Flattening nested streams
135 -- ** Flattening nested streams
138 , concatMapM
136 , concatMapM
139 , concatMap
137 , concatMap
141 -- ** Grouping
140 -- ** Grouping
142 , groupsOf
141 , groupsOf
@@ -284,6 +283,7 @@ import Streamly.Memory.Array.Types (Array(..))
284import Streamly.Fold.Types (Fold(..))
283import Streamly.Fold.Types (Fold(..))
285import Streamly.Pipe.Types (Pipe(..), PipeState(..))
284import Streamly.Pipe.Types (Pipe(..), PipeState(..))
286import Streamly.SVar (MonadAsync, defState, adaptState)
285import Streamly.SVar (MonadAsync, defState, adaptState)
286+import Streamly.Unfold.Types (Unfold(..))
288import Streamly.Streams.StreamD.Type
288import Streamly.Streams.StreamD.Type
@@ -386,14 +386,6 @@ replicateM n p = Stream step n
387 return $ Yield x (i - 1)
387 return $ Yield x (i - 1)
389−-- | For use with flatten
390−{-# INLINE replicateGen #-}
391−replicateGen :: Monad m => (a, Int) -> m (Step (a, Int) a)
392−replicateGen (x, i) = return $
395− else Yield x (x, (i - 1))
397{-# INLINE_NORMAL replicate #-}
389{-# INLINE_NORMAL replicate #-}
398replicate :: Monad m => Int -> a -> Stream m a
390replicate :: Monad m => Int -> a -> Stream m a
399replicate n x = replicateM n (return x)
391replicate n x = replicateM n (return x)
@@ -1702,6 +1694,40 @@ stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1702mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1694mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1703mapM_ m = drain . mapM m
1695mapM_ m = drain . mapM m
1697+-------------------------------------------------------------------------------
1698+-- Stream transformations using Unfolds
1699+-------------------------------------------------------------------------------
1701+-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
1702+-- to streams and then flattens the generated streams into a single output
1705+-- This is like 'concatMap' but uses an unfold with an explicit state to
1706+-- generate the stream instead of a 'Stream' type generator. This allows better
1707+-- optimization via fusion. This can be many times more efficient than
1710+{-# INLINE_NORMAL concatMapU #-}
1711+concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1712+concatMapU (Unfold istep inject) (Stream ostep u) = Stream step (Left u)
1714+ {-# INLINE_LATE step #-}
1715+ step gst (Left t) = do
1716+ r <- ostep (adaptState gst) t
1720+ s `seq` return (Skip (Right (s, t')))
1721+ Skip t' -> return $ Skip (Left t')
1722+ Stop -> return $ Stop
1724+ step _ (Right (s, t)) = do
1727+ Yield x s' -> Yield x (Right (s', t))
1728+ Skip s' -> Skip (Right (s', t))
1729+ Stop -> Skip (Left t)
1705------------------------------------------------------------------------------
1731------------------------------------------------------------------------------
1706-- Exceptions
1732-- Exceptions
1707------------------------------------------------------------------------------
1733------------------------------------------------------------------------------