3-- Module : Streamly.Internal.Data.Stream.Transformer
4-- Copyright : (c) 2018 Composewell Technologies
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
10-- Transform the underlying monad of a stream using a monad transfomer.
12module Streamly.Internal.Data.Stream.Transformer
17 -- * Transform Inner Monad
29import Control.Monad.Trans.Class (MonadTrans(lift))
30import Control.Monad.Trans.Reader (ReaderT)
31import Control.Monad.Trans.State.Strict (StateT)
32import GHC.Types (SPEC(..))
33import Streamly.Internal.Data.SVar.Type (defState, adaptState)
35import qualified Control.Monad.Trans.Reader as Reader
36import qualified Control.Monad.Trans.State.Strict as State
38import Streamly.Internal.Data.Stream.Type
40#include "DocTestDataStream.hs"
42-- | Lazy left fold to a transformer monad.
44{-# INLINE_NORMAL foldlT #-}
45foldlT :: (Monad m, Monad (s m), MonadTrans s)
46 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
47foldlT fstep begin (Stream step state) = go SPEC begin state
50 r <- lift $ step defState st
52 Yield x s -> go SPEC (fstep acc x) s
53 Skip s -> go SPEC acc s
56-- | Right fold to a transformer monad. This is the most general right fold
57-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
58-- implementation can be more efficient:
60-- >>> foldrS = Stream.foldrT
62-- >>> step f x xs = lift $ f x (runIdentityT xs)
63-- >>> foldrM f z s = runIdentityT $ Stream.foldrT (step f) (lift z) s
65-- 'foldrT' can be used to translate streamly streams to other transformer
66-- monads e.g. to a different streaming type.
69{-# INLINE_NORMAL foldrT #-}
70foldrT :: (Monad m, Monad (t m), MonadTrans t)
71 => (a -> t m b -> t m b) -> t m b -> Stream m a -> t m b
72foldrT f final (Stream step state) = go SPEC state
74 {-# INLINE_LATE go #-}
76 r <- lift $ step defState st
78 Yield x s -> f x (go SPEC s)
82-------------------------------------------------------------------------------
83-- Transform Inner Monad
84-------------------------------------------------------------------------------
86-- | Lift the inner monad @m@ of @Stream m a@ to @t m@ where @t@ is a monad
89{-# INLINE_NORMAL liftInner #-}
90liftInner :: (Monad m, MonadTrans t, Monad (t m))
91 => Stream m a -> Stream (t m) a
92liftInner (Stream step state) = Stream step' state
94 {-# INLINE_LATE step' #-}
96 r <- lift $ step (adaptState gst) st
98 Yield x s -> Yield x s
102------------------------------------------------------------------------------
103-- Sharing read only state in a stream
104------------------------------------------------------------------------------
106-- | Evaluate the inner monad of a stream as 'ReaderT'.
108{-# INLINE_NORMAL runReaderT #-}
109runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
110runReaderT env (Stream step state) = Stream step' (state, env)
112 {-# INLINE_LATE step' #-}
113 step' gst (st, action) = do
115 r <- Reader.runReaderT (step (adaptState gst) st) sv
117 Yield x s -> Yield x (s, return sv)
118 Skip s -> Skip (s, return sv)
121-- | Run a stream transformation using a given environment.
123{-# INLINE usingReaderT #-}
127 -> (Stream (ReaderT r m) a -> Stream (ReaderT r m) a)
130usingReaderT r f xs = runReaderT r $ f $ liftInner xs
132------------------------------------------------------------------------------
133-- Sharing read write state in a stream
134------------------------------------------------------------------------------
136-- | Evaluate the inner monad of a stream as 'StateT'.
138-- >>> evalStateT s = fmap snd . Stream.runStateT s
140{-# INLINE_NORMAL evalStateT #-}
141evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
142evalStateT initial (Stream step state) = Stream step' (state, initial)
144 {-# INLINE_LATE step' #-}
145 step' gst (st, action) = do
147 (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
149 Yield x s -> Yield x (s, return sv')
150 Skip s -> Skip (s, return sv')
153-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
154-- state and value pair after each step.
156{-# INLINE_NORMAL runStateT #-}
157runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
158runStateT initial (Stream step state) = Stream step' (state, initial)
160 {-# INLINE_LATE step' #-}
161 step' gst (st, action) = do
163 (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
165 Yield x s -> Yield (sv', x) (s, return sv')
166 Skip s -> Skip (s, return sv')
169-- | Run a stateful (StateT) stream transformation using a given state.
171-- >>> usingStateT s f = Stream.evalStateT s . f . Stream.liftInner
175{-# INLINE usingStateT #-}
179 -> (Stream (StateT s m) a -> Stream (StateT s m) a)
182usingStateT s f = evalStateT s . f . liftInner
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list