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