@@ -133,8 +133,6 @@ module Streamly.Internal.Prelude
133133
134134 -- * Transformation
135135 , transform
136− , hoist
137− , generally
138136
139137 -- ** Mapping
140138 , Serial.map
@@ -376,6 +374,17 @@ module Streamly.Internal.Prelude
376374 , finally
377375 , handle
378376
377+ -- * Generalize Inner Monad
378+ , hoist
379+ , generally
380+
381+ -- * Transform Inner Monad
382+ , liftInner
383+ , runReaderT
384+ , evalStateT
385+ , usingStateT
386+ , runStateT
387+
379388 -- * Diagnostics
380389 , inspectMode
381390
@@ -399,6 +408,8 @@ import Control.Exception (Exception)
399408import Control.Monad (void)
400409import Control.Monad.Catch (MonadCatch)
401410import Control.Monad.IO.Class (MonadIO(..))
411+import Control.Monad.Reader (ReaderT)
412+import Control.Monad.State.Strict (StateT)
402413import Control.Monad.Trans (MonadTrans(..))
403414import Data.Functor.Identity (Identity (..))
404415import Data.Heap (Entry(..))
@@ -1471,15 +1482,6 @@ toPureRev = foldl' (flip K.cons) K.nil
14711482transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
14721483transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
14731484
1474−{-# INLINE hoist #-}
1475−hoist :: (Monad m, Monad n)
1476− => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
1477−hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
1478−
1479−{-# INLINE generally #-}
1480−generally :: (IsStream t, Monad m) => t Identity a -> t m a
1481−generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
1482−
14831485------------------------------------------------------------------------------
14841486-- Transformation by Folding (Scans)
14851487------------------------------------------------------------------------------
@@ -3696,3 +3698,84 @@ handle :: (IsStream t, MonadCatch m, Exception e)
36963698 => (e -> t m a) -> t m a -> t m a
36973699handle handler xs =
36983700 D.fromStreamD $ D.handle (\e -> D.toStreamD $ handler e) $ D.toStreamD xs
3701+
3702+------------------------------------------------------------------------------
3703+-- Generalize the underlying monad
3704+------------------------------------------------------------------------------
3705+
3706+-- | Transform the inner monad of a stream using a natural transformation.
3707+--
3708+-- / Internal/
3709+--
3710+{-# INLINE hoist #-}
3711+hoist :: (Monad m, Monad n)
3712+ => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
3713+hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
3714+
3715+-- | Generalize the inner monad of the stream from 'Identity' to any monad.
3716+--
3717+-- / Internal/
3718+--
3719+{-# INLINE generally #-}
3720+generally :: (IsStream t, Monad m) => t Identity a -> t m a
3721+generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
3722+
3723+------------------------------------------------------------------------------
3724+-- Add and remove a monad transformer
3725+------------------------------------------------------------------------------
3726+
3727+-- | Lift the inner monad of a stream using a monad transformer.
3728+--
3729+-- / Internal/
3730+--
3731+{-# INLINE liftInner #-}
3732+liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
3733+ => t m a -> t (tr m) a
3734+liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
3735+
3736+-- | Evaluate the inner monad of a stream as 'ReaderT'.
3737+--
3738+-- / Internal/
3739+--
3740+{-# INLINE runReaderT #-}
3741+runReaderT :: (IsStream t, Monad m) => s -> t (ReaderT s m) a -> t m a
3742+runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
3743+
3744+-- | Evaluate the inner monad of a stream as 'StateT'.
3745+--
3746+-- This is supported only for 'SerialT' as concurrent state updation may not be
3747+-- safe.
3748+--
3749+-- / Internal/
3750+--
3751+{-# INLINE evalStateT #-}
3752+evalStateT :: Monad m => s -> SerialT (StateT s m) a -> SerialT m a
3753+evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
3754+
3755+-- | Run a stateful (StateT) stream transformation using a given state.
3756+--
3757+-- This is supported only for 'SerialT' as concurrent state updation may not be
3758+-- safe.
3759+--
3760+-- / Internal/
3761+--
3762+{-# INLINE usingStateT #-}
3763+usingStateT
3764+ :: Monad m
3765+ => s
3766+ -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
3767+ -> SerialT m a
3768+ -> SerialT m a
3769+usingStateT s f xs = evalStateT s $ f $ liftInner xs
3770+
3771+-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
3772+-- state and value pair after each step.
3773+--
3774+-- This is supported only for 'SerialT' as concurrent state updation may not be
3775+-- safe.
3776+--
3777+-- / Internal/
3778+--
3779+{-# INLINE runStateT #-}
3780+runStateT :: Monad m => s -> SerialT (StateT s m) a -> SerialT m (s, a)
3781+runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)