@@ -410,6 +410,10 @@ module Streamly.Internal.Data.Fold.Type
410410 , close
411411 , isClosed
412412
413+ -- * Lifting inner monad
414+ , hoist
415+ , generally
416+
413417 -- * Deprecated
414418 , foldr
415419 , serialWith
@@ -422,6 +426,7 @@ import Control.Applicative (liftA2)
422426import Control.Monad ((>=>))
423427import Data.Bifunctor (Bifunctor(..))
424428import Data.Either (fromLeft, fromRight, isLeft, isRight)
429+import Data.Functor.Identity (Identity(..))
425430import Fusion.Plugin.Types (Fuse(..))
426431import Streamly.Internal.Data.Fold.Step (Step(..), mapMStep, chainStepM)
427432import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
@@ -1817,3 +1822,22 @@ refoldMany1 (Refold sstep sinject sextract) (Fold cstep cinitial cextract) =
18171822refold :: Monad m => Refold m b a c -> Fold m a b -> Fold m a c
18181823refold (Refold step inject extract) f =
18191824 Fold step (extractM f >>= inject) extract
1825+
1826+------------------------------------------------------------------------------
1827+-- hoist
1828+------------------------------------------------------------------------------
1829+
1830+-- | Change the underlying monad of a fold
1831+--
1832+-- /Pre-release/
1833+hoist :: (forall x. m x -> n x) -> Fold m a b -> Fold n a b
1834+hoist f (Fold step initial extract) =
1835+ Fold (\x a -> f $ step x a) (f initial) (f . extract)
1836+
1837+-- | Adapt a pure fold to any monad
1838+--
1839+-- >>> generally = Fold.hoist (return . runIdentity)
1840+--
1841+-- /Pre-release/
1842+generally :: Monad m => Fold Identity a b -> Fold m a b
1843+generally = hoist (return . runIdentity)