on aa2b166 help sign in
152 lines 4.6 kB history raw
1-- |
2-- Module : Streamly.Internal.Data.Stream.IsStream.Lift
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
7-- Portability : GHC
9module Streamly.Internal.Data.Stream.IsStream.Lift
10 (
11 -- * Generalize Inner Monad
12 hoist
13 , generally
15 -- * Transform Inner Monad
16 , liftInner
17 , usingReaderT
18 , runReaderT
19 , evalStateT
20 , usingStateT
21 , runStateT
22 )
23where
25#include "inline.hs"
27import Control.Monad.Trans.Reader (ReaderT)
28import Control.Monad.Trans.State.Strict (StateT)
29import Control.Monad.Trans.Class (MonadTrans(..))
30import Data.Functor.Identity (Identity (..))
31import Streamly.Internal.Data.Stream.IsStream.Type
32 (IsStream(..), fromStreamS, toStreamS, fromStreamD, toStreamD)
33import Streamly.Internal.Data.Stream.Serial (SerialT)
35import qualified Streamly.Internal.Data.Stream.StreamD as D
36#ifdef USE_STREAMK_ONLY
37import qualified Streamly.Internal.Data.Stream.StreamK as S
38#else
39import qualified Streamly.Internal.Data.Stream.StreamD as S
40#endif
42------------------------------------------------------------------------------
43-- Generalize the underlying monad
44------------------------------------------------------------------------------
46-- | Transform the inner monad of a stream using a natural transformation.
47--
48-- / Internal/
49--
50{-# INLINE hoist #-}
51hoist :: (Monad m, Monad n)
52 => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
53hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
55-- | Generalize the inner monad of the stream from 'Identity' to any monad.
56--
57-- / Internal/
58--
59{-# INLINE generally #-}
60generally :: (IsStream t, Monad m) => t Identity a -> t m a
61generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
63------------------------------------------------------------------------------
64-- Add and remove a monad transformer
65------------------------------------------------------------------------------
67-- | Lift the inner monad @m@ of a stream @t m a@ to @tr m@ using the monad
68-- transformer @tr@.
69--
70-- @since 0.8.0
71--
72{-# INLINE liftInner #-}
73liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
74 => t m a -> t (tr m) a
75liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
77------------------------------------------------------------------------------
78-- Sharing read only state in a stream
79------------------------------------------------------------------------------
81-- | Evaluate the inner monad of a stream as 'ReaderT'.
82--
83-- @since 0.8.0
84--
85{-# INLINE runReaderT #-}
86runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a
87runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
89-- | Run a stream transformation using a given environment.
90--
91-- See also: 'Serial.map'
92--
93-- / Internal/
94--
95{-# INLINE usingReaderT #-}
96usingReaderT
97 :: (Monad m, IsStream t)
98 => m r
99 -> (t (ReaderT r m) a -> t (ReaderT r m) a)
100 -> t m a
101 -> t m a
102usingReaderT r f xs = runReaderT r $ f $ liftInner xs
104------------------------------------------------------------------------------
105-- Sharing read write state in a stream
106------------------------------------------------------------------------------
108-- | Evaluate the inner monad of a stream as 'StateT'.
109--
110-- This is supported only for 'SerialT' as concurrent state updation may not be
111-- safe.
112--
113-- > evalStateT s = Stream.map snd . Stream.runStateT s
114--
115-- / Internal/
116--
117{-# INLINE evalStateT #-}
118evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a
119-- evalStateT s = fmap snd . runStateT s
120evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
122-- | Run a stateful (StateT) stream transformation using a given state.
123--
124-- This is supported only for 'SerialT' as concurrent state updation may not be
125-- safe.
126--
127-- > usingStateT s f = evalStateT s . f . liftInner
128--
129-- See also: 'scanl''
130--
131-- / Internal/
132--
133{-# INLINE usingStateT #-}
134usingStateT
135 :: Monad m
136 => m s
137 -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
138 -> SerialT m a
139 -> SerialT m a
140usingStateT s f = evalStateT s . f . liftInner
142-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
143-- state and value pair after each step.
144--
145-- This is supported only for 'SerialT' as concurrent state updation may not be
146-- safe.
147--
148-- @since 0.8.0
149--
150{-# INLINE runStateT #-}
151runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a)
152runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)