@@ -112,6 +112,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
112112 -- ** Folding
113113 -- | Apply folds on a stream.
114114 , foldMany
115+ , foldIterateM
115116
116117 -- ** Parsing
117118 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
@@ -957,6 +958,50 @@ gintercalate
957958 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
958959 -}
959960
961+------------------------------------------------------------------------------
962+-- Folding
963+------------------------------------------------------------------------------
964+
965+{-# ANN type FIterState Fuse #-}
966+data FIterState s f m a b
967+ = FIterInit s f
968+ | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
969+ | FIterYield b (FIterState s f m a b)
970+ | FIterStop
971+
972+{-# INLINE_NORMAL foldIterateM #-}
973+foldIterateM ::
974+ Monad m => (b -> m (FL.Fold m a b)) -> b -> Stream m a -> Stream m b
975+foldIterateM func seed0 (Stream step state) =
976+ Stream stepOuter (FIterInit state seed0)
977+
978+ where
979+
980+ {-# INLINE iterStep #-}
981+ iterStep from st fstep extract = do
982+ res <- from
983+ return
984+ $ Skip
985+ $ case res of
986+ FL.Partial fs -> FIterStream st fstep fs extract
987+ FL.Done fb -> FIterYield fb $ FIterInit st fb
988+
989+ {-# INLINE_LATE stepOuter #-}
990+ stepOuter _ (FIterInit st seed) = do
991+ (FL.Fold fstep initial extract) <- func seed
992+ iterStep initial st fstep extract
993+ stepOuter gst (FIterStream st fstep fs extract) = do
994+ r <- step (adaptState gst) st
995+ case r of
996+ Yield x s -> do
997+ iterStep (fstep fs x) s fstep extract
998+ Skip s -> return $ Skip $ FIterStream s fstep fs extract
999+ Stop -> do
1000+ b <- extract fs
1001+ return $ Skip $ FIterYield b FIterStop
1002+ stepOuter _ (FIterYield a next) = return $ Yield a next
1003+ stepOuter _ FIterStop = return Stop
1004+
9601005------------------------------------------------------------------------------
9611006-- Parsing
9621007------------------------------------------------------------------------------