@@ -113,6 +113,7 @@ module Streamly.Internal.Data.Fold
113113 --, lsequence
114114 , lmapM
115115 , scan
116+ , postscan
116117 , indexed
117118
118119 -- ** Filtering
@@ -390,6 +391,8 @@ scan (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
390391
391392 where
392393
394+ -- XXX It can be moved out and used for both scan and postscan
395+ {-# INLINE runStep #-}
393396 runStep actionL sR = do
394397 rL <- actionL
395398 case rL of
@@ -416,6 +419,47 @@ scan (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
416419
417420 extract = extractR . snd
418421
422+-- | Postscan the input of a 'Fold' to change it in a stateful manner using
423+-- another 'Fold'.
424+-- /Pre-release/
425+{-# INLINE postscan #-}
426+postscan :: Monad m => Fold m a b -> Fold m b c -> Fold m a c
427+postscan (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
428+ Fold step initial extract
429+
430+ where
431+
432+ {-# INLINE runStep #-}
433+ runStep actionL sR = do
434+ rL <- actionL
435+ case rL of
436+ Done bL -> do
437+ rR <- stepR sR bL
438+ case rR of
439+ Partial sR1 -> Done <$> extractR sR1
440+ Done bR -> return $ Done bR
441+ Partial sL -> do
442+ !b <- extractL sL
443+ rR <- stepR sR b
444+ return
445+ $ case rR of
446+ Partial sR1 -> Partial (sL, sR1)
447+ Done bR -> Done bR
448+
449+ initial = do
450+ r <- initialR
451+ rL <- initialL
452+ case r of
453+ Partial sR ->
454+ case rL of
455+ Done _ -> Done <$> extractR sR
456+ Partial sL -> return $ Partial (sL, sR)
457+ Done b -> return $ Done b
458+
459+ step (sL, sR) x = runStep (stepL sL x) sR
460+
461+ extract = extractR . snd
462+
419463------------------------------------------------------------------------------
420464-- Left folds
421465------------------------------------------------------------------------------