on 3feeec2 help sign in
153 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.Prelude (fromStreamS, toStreamS)
32import Streamly.Internal.Data.Stream.Serial (SerialT)
33import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
34import Streamly.Internal.Data.Stream.StreamK (IsStream)
36import qualified Streamly.Internal.Data.Stream.StreamD as D
37#ifdef USE_STREAMK_ONLY
38import qualified Streamly.Internal.Data.Stream.StreamK as S
39#else
40import qualified Streamly.Internal.Data.Stream.StreamD as S
41#endif
43------------------------------------------------------------------------------
44-- Generalize the underlying monad
45------------------------------------------------------------------------------
47-- | Transform the inner monad of a stream using a natural transformation.
48--
49-- / Internal/
50--
51{-# INLINE hoist #-}
52hoist :: (Monad m, Monad n)
53 => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
54hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
56-- | Generalize the inner monad of the stream from 'Identity' to any monad.
57--
58-- / Internal/
59--
60{-# INLINE generally #-}
61generally :: (IsStream t, Monad m) => t Identity a -> t m a
62generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
64------------------------------------------------------------------------------
65-- Add and remove a monad transformer
66------------------------------------------------------------------------------
68-- | Lift the inner monad @m@ of a stream @t m a@ to @tr m@ using the monad
69-- transformer @tr@.
70--
71-- @since 0.8.0
72--
73{-# INLINE liftInner #-}
74liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
75 => t m a -> t (tr m) a
76liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
78------------------------------------------------------------------------------
79-- Sharing read only state in a stream
80------------------------------------------------------------------------------
82-- | Evaluate the inner monad of a stream as 'ReaderT'.
83--
84-- @since 0.8.0
85--
86{-# INLINE runReaderT #-}
87runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a
88runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
90-- | Run a stream transformation using a given environment.
91--
92-- See also: 'Serial.map'
93--
94-- / Internal/
95--
96{-# INLINE usingReaderT #-}
97usingReaderT
98 :: (Monad m, IsStream t)
99 => m r
100 -> (t (ReaderT r m) a -> t (ReaderT r m) a)
101 -> t m a
102 -> t m a
103usingReaderT r f xs = runReaderT r $ f $ liftInner xs
105------------------------------------------------------------------------------
106-- Sharing read write state in a stream
107------------------------------------------------------------------------------
109-- | Evaluate the inner monad of a stream as 'StateT'.
110--
111-- This is supported only for 'SerialT' as concurrent state updation may not be
112-- safe.
113--
114-- > evalStateT s = Stream.map snd . Stream.runStateT s
115--
116-- / Internal/
117--
118{-# INLINE evalStateT #-}
119evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a
120-- evalStateT s = fmap snd . runStateT s
121evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
123-- | Run a stateful (StateT) stream transformation using a given state.
124--
125-- This is supported only for 'SerialT' as concurrent state updation may not be
126-- safe.
127--
128-- > usingStateT s f = evalStateT s . f . liftInner
129--
130-- See also: 'scanl''
131--
132-- / Internal/
133--
134{-# INLINE usingStateT #-}
135usingStateT
136 :: Monad m
137 => m s
138 -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
139 -> SerialT m a
140 -> SerialT m a
141usingStateT s f = evalStateT s . f . liftInner
143-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
144-- state and value pair after each step.
145--
146-- This is supported only for 'SerialT' as concurrent state updation may not be
147-- safe.
148--
149-- @since 0.8.0
150--
151{-# INLINE runStateT #-}
152runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a)
153runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)