@@ -209,6 +209,7 @@ module Streamly.Internal.Data.Fold.Type
209 -- * Folds
209 -- * Folds
210 , fromPure
210 , fromPure
211 , fromEffect
211 , fromEffect
214 , toStreamK
215 , toStreamK
@@ -248,6 +249,8 @@ module Streamly.Internal.Data.Fold.Type
248 , ManyState
249 , ManyState
250 , manyPost
251 , manyPost
251 , chunksOf
254 , chunksOf
253 -- ** Nesting
256 -- ** Nesting
@@ -258,10 +261,6 @@ module Streamly.Internal.Data.Fold.Type
259 , duplicate
262 , duplicate
@@ -271,7 +270,7 @@ import Data.Maybe (isJust, fromJust)
271import Fusion.Plugin.Types (Fuse(..))
270import Fusion.Plugin.Types (Fuse(..))
272import Streamly.Internal.Data.Fold.Step (Step(..), mapMStep, chainStepM)
271import Streamly.Internal.Data.Fold.Step (Step(..), mapMStep, chainStepM)
273import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
272import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
274−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
273+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
275import Streamly.Internal.Data.Consumer.Type (Consumer(..))
274import Streamly.Internal.Data.Consumer.Type (Consumer(..))
277import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
276import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
@@ -505,18 +504,18 @@ mkFoldM_ :: Monad m => (b -> a -> m (Step b b)) -> m (Step b b) -> Fold m a b
505mkFoldM_ step initial = mkFoldM step initial return
504mkFoldM_ step initial = mkFoldM step initial return
507------------------------------------------------------------------------------
506------------------------------------------------------------------------------
508−-- Fold2
507+-- Consumer
509------------------------------------------------------------------------------
508------------------------------------------------------------------------------
511-- This is similar to how we run an Unfold to generate a Stream. A Fold is like
510-- This is similar to how we run an Unfold to generate a Stream. A Fold is like
512-- a Stream and a Fold2 is like an Unfold.
511-- a Stream and a Fold2 is like an Unfold.
514−-- | Convert more general type 'Fold2' into a simpler type 'Fold'
513+-- | Make a fold from a consumer.
516-- /Internal/
515-- /Internal/
517−simplify :: Functor m => Consumer m c a b -> c -> Fold m a b
516+fromConsumer :: Consumer m c a b -> c -> Fold m a b
518−simplify (Consumer step inject extract) c =
517+fromConsumer (Consumer step inject extract) c =
519− Fold (\x a -> Partial <$> step x a) (Partial <$> inject c) extract
518+ Fold step (inject c) extract
521------------------------------------------------------------------------------
520------------------------------------------------------------------------------
522-- Basic Folds
521-- Basic Folds
@@ -1312,32 +1311,102 @@ manyPost (Fold sstep sinitial sextract) (Fold cstep cinitial cextract) =
1312chunksOf :: Monad m => Int -> Fold m a b -> Fold m b c -> Fold m a c
1311chunksOf :: Monad m => Int -> Fold m a b -> Fold m b c -> Fold m a c
1313chunksOf n split = many (take n split)
1312chunksOf n split = many (take n split)
1315−-- |
1314+-- | Like 'many' but uses a 'Consumer' for collecting.
1316+{-# INLINE consumeMany #-}
1317+consumeMany :: Monad m => Fold m a b -> Consumer m x b c -> Consumer m x a c
1318+consumeMany (Fold sstep sinitial sextract) (Consumer cstep cinject cextract) =
1319+ Consumer step inject extract
1323+ -- cs = collect state
1324+ -- ss = split state
1325+ -- cres = collect state result
1326+ -- sres = split state result
1327+ -- cb = collect done
1330+ -- Caution! There is mutual recursion here, inlining the right functions is
1333+ {-# INLINE split #-}
1336+ Partial ss -> return $ Partial $ Tuple' cs (f ss)
1337+ Done sb -> cstep cs sb >>= collect
1339+ {-# INLINE collect #-}
1342+ Partial cs -> sinitial >>= split cs Left
1343+ Done cb -> return $ Done cb
1345+ inject x = cinject x >>= collect
1347+ {-# INLINE step_ #-}
1348+ step_ ss cs a = sstep ss a >>= split cs Right
1350+ {-# INLINE step #-}
1351+ step (Tuple' cs (Left ss)) a = step_ ss cs a
1352+ step (Tuple' cs (Right ss)) a = step_ ss cs a
1354+ -- Do not extract the split fold if no item was consumed.
1355+ extract (Tuple' cs (Left _)) = cextract cs
1356+ extract (Tuple' cs (Right ss )) = do
1357+ cres <- sextract ss >>= cstep cs
1359+ Partial s -> cextract s
1362+{-# ANN type ConsumeManyState Fuse #-}
1363+data ConsumeManyState x cs ss = ConsumeMany x cs (Either ss ss)
1365+-- | Like 'many' but uses a 'Consumer' for splitting.
1317-- /Internal/
1367-- /Internal/
1318−{-# INLINE chunksOf2 #-}
1368+{-# INLINE consumeMany1 #-}
1319−chunksOf2 :: Monad m =>
1320− Int -> Fold m a b -> Consumer m x b c -> Consumer m x a c
1369+consumeMany1 :: Monad m => Consumer m x a b -> Fold m b c -> Consumer m x a c
1321−chunksOf2 n (Fold step1 initial1 extract1) (Consumer step2 inject2 extract2) =
1370+consumeMany1 (Consumer sstep sinject sextract) (Fold cstep cinitial cextract) =
1322− Consumer step' inject' extract'
1371+ Consumer step inject extract
1326− loopUntilPartial s = do
1375+ -- cs = collect state
1327− res <- initial1
1376+ -- ss = split state
1328− case res of
1377+ -- cres = collect state result
1329− Partial fs -> return $ Tuple3' 0 fs s
1378+ -- sres = split state result
1330− Done _ -> loopUntilPartial s
1379+ -- cb = collect done
1382+ -- Caution! There is mutual recursion here, inlining the right functions is
1332− inject' x = inject2 x >>= loopUntilPartial
1385+ {-# INLINE split #-}
1386+ split x cs f sres =
1388+ Partial ss -> return $ Partial $ ConsumeMany x cs (f ss)
1389+ Done sb -> cstep cs sb >>= collect x
1334− step' (Tuple3' i r1 r2) a =
1391+ {-# INLINE collect #-}
1335− if i < n
1392+ collect x cres =
1338− case res of
1393+ case cres of
1339− Partial s -> return $ Tuple3' (i + 1) s r2
1394+ Partial cs -> sinject x >>= split x cs Left
1340− Done b -> step2 r2 b >>= loopUntilPartial
1395+ Done cb -> return $ Done cb
1341− else extract1 r1 >>= step2 r2 >>= loopUntilPartial
1396+
1397+ inject x = cinitial >>= collect x
1343− extract' (Tuple3' _ r1 r2) = extract1 r1 >>= step2 r2 >>= extract2
1399+ {-# INLINE step_ #-}
1400+ step_ x ss cs a = sstep ss a >>= split x cs Right
1402+ {-# INLINE step #-}
1403+ step (ConsumeMany x cs (Left ss)) a = step_ x ss cs a
1404+ step (ConsumeMany x cs (Right ss)) a = step_ x ss cs a
1406+ -- Do not extract the split fold if no item was consumed.
1407+ extract (ConsumeMany _ cs (Left _)) = cextract cs
1408+ extract (ConsumeMany _ cs (Right ss )) = do
1409+ cres <- sextract ss >>= cstep cs
1411+ Partial s -> cextract s