on master help sign in
Implement foldBreak using CPS
93d8e01Harendra Kumar
core/src/Streamly/Internal/Data/Stream/StreamK.hs+25
@@ -82,6 +82,7 @@ module Streamly.Internal.Data.Stream.StreamK
82 , foldlx'
82 , foldlx'
83 , foldlMx'
83 , foldlMx'
84 , fold
84 , fold
85+ , foldBreak
85
86
86 -- ** Specialized Folds
87 -- ** Specialized Folds
87 , drain
88 , drain
@@ -327,6 +328,30 @@ fold (FL.Fold step begin done) m = do
327 FL.Done b1 -> return b1
328 FL.Done b1 -> return b1
328 in foldStream defState yieldk single stop m1
329 in foldStream defState yieldk single stop m1
329
330
331+{-# INLINE foldBreak #-}
332+foldBreak :: Monad m => FL.Fold m a b -> Stream m a -> m (b, Stream m a)
333+foldBreak (FL.Fold step begin done) m = do
334+ res <- begin
335+ case res of
336+ FL.Partial fs -> go fs m
337+ FL.Done fb -> return (fb, m)
338+
339+ where
340+
341+ go !acc m1 =
342+ let stop = (, nil) <$> done acc
343+ single a =
344+ step acc a
345+ >>= \case
346+ FL.Partial s -> (, nil) <$> done s
347+ FL.Done b1 -> return (b1, nil)
348+ yieldk a r =
349+ step acc a
350+ >>= \case
351+ FL.Partial s -> go s r
352+ FL.Done b1 -> return (b1, r)
353+ in foldStream defState yieldk single stop m1
354+
330-- | Like 'foldl'' but with a monadic step function.
355-- | Like 'foldl'' but with a monadic step function.
331{-# INLINE foldlM' #-}
356{-# INLINE foldlM' #-}
332foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
357foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+14−2
@@ -83,6 +83,7 @@ import qualified Streamly.Internal.Data.Stream.Async as Async
83import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
83import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
84import qualified Streamly.Internal.Data.Stream.Parallel as Par
84import qualified Streamly.Internal.Data.Stream.Parallel as Par
85import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
85import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
86+import qualified Streamly.Internal.Data.Stream.StreamK as K
86import qualified Streamly.Internal.Data.Stream.StreamD as D
87import qualified Streamly.Internal.Data.Stream.StreamD as D
87#ifdef USE_STREAMK_ONLY
88#ifdef USE_STREAMK_ONLY
88import qualified Streamly.Internal.Data.Stream.StreamK as S
89import qualified Streamly.Internal.Data.Stream.StreamK as S
@@ -309,15 +310,26 @@ foldContinue f s = D.foldContinue f $ IsStream.toStreamD s
309fold :: Monad m => Fold m a b -> SerialT m a -> m b
310fold :: Monad m => Fold m a b -> SerialT m a -> m b
310fold fl (SerialT strm) = D.fold fl $ D.fromStreamK strm
311fold fl (SerialT strm) = D.fold fl $ D.fromStreamK strm
311
312
312−-- XXX This shows quadratic performance when used recursively perhaps because
313+-- | Like 'fold' but also returns the remaining stream.
313−-- of StreamK to StreamD conversions not getting eliminated sue to recursion.
314+--
315+-- /Inhibits stream fusion/
316+--
314{-# INLINE foldBreak #-}
317{-# INLINE foldBreak #-}
315foldBreak :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
318foldBreak :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
319+{-
320+-- XXX This shows quadratic performance when used recursively perhaps because
321+-- of StreamK to StreamD conversions not getting eliminated sue to recursion.
316foldBreak fl (SerialT strm) = fmap f $ D.foldBreak fl $ D.fromStreamK strm
322foldBreak fl (SerialT strm) = fmap f $ D.foldBreak fl $ D.fromStreamK strm
317
323
318 where
324 where
319
325
320 f (b, str) = (b, SerialT (D.toStreamK str))
326 f (b, str) = (b, SerialT (D.toStreamK str))
327+-}
328+foldBreak fl (SerialT strm) = fmap f $ K.foldBreak fl strm
329+
330+ where
331+
332+ f (b, str) = (b, SerialT str)
321
333
322------------------------------------------------------------------------------
334------------------------------------------------------------------------------
323-- Transformation
335-- Transformation