on master help sign in
Move Transformer ops to a separate module

For better modularity.

commita358a7424831a6fd6936d6efacc7b68ef26f6e12 authorHarendra Kumar <harendra@composewell.com> dateFri 18 Nov 2022, 12:08 (4 years ago) parentec94487
9 files changed+256−161
core/src/Streamly/Internal/Data/Stream.hs+2 core/src/Streamly/Internal/Data/Stream/Lift.hs+4−92 core/src/Streamly/Internal/Data/Stream/StreamD.hs+2 core/src/Streamly/Internal/Data/Stream/StreamD/Lift.hs−68 core/src/Streamly/Internal/Data/Stream/StreamD/Transformer.hs+87 core/src/Streamly/Internal/Data/Stream/StreamK/Transformer.hs+52 core/src/Streamly/Internal/Data/Stream/Top.hs+1−1 core/src/Streamly/Internal/Data/Stream/Transformer.hs+105 core/streamly-core.cabal+3
core/src/Streamly/Internal/Data/Stream.hs+2
@@ -13,6 +13,7 @@ module Streamly.Internal.Data.Stream
1313 , module Streamly.Internal.Data.Stream.Expand
1414 , module Streamly.Internal.Data.Stream.Generate
1515 , module Streamly.Internal.Data.Stream.Lift
16+ , module Streamly.Internal.Data.Stream.Transformer
1617 , module Streamly.Internal.Data.Stream.Reduce
1718 , module Streamly.Internal.Data.Stream.Transform
1819 , module Streamly.Internal.Data.Stream.Top
@@ -24,6 +25,7 @@ import Streamly.Internal.Data.Stream.Exception
2425import Streamly.Internal.Data.Stream.Expand
2526import Streamly.Internal.Data.Stream.Generate
2627import Streamly.Internal.Data.Stream.Lift
28+import Streamly.Internal.Data.Stream.Transformer
2729import Streamly.Internal.Data.Stream.Reduce
2830import Streamly.Internal.Data.Stream.Top
2931import Streamly.Internal.Data.Stream.Transform
core/src/Streamly/Internal/Data/Stream/Lift.hs+4−92
@@ -11,27 +11,12 @@ module Streamly.Internal.Data.Stream.Lift
1111 -- * Generalize Inner Monad
1212 hoist
1313 , generally
14−
15− -- * Transform Inner Monad
16− , liftInner
17− , usingReaderT
18− , runReaderT
19− , evalStateT
20− , usingStateT
21− , runStateT
2214 )
2315where
2416
25−#include "inline.hs"
26−
27−import Control.Monad.Trans.Reader (ReaderT)
28−import Control.Monad.Trans.State.Strict (StateT)
29−import Control.Monad.Trans.Class (MonadTrans(..))
3017import Data.Functor.Identity (Identity (..))
31−import Streamly.Internal.Data.Stream.Type
32− (Stream, fromStreamK, toStreamK, fromStreamD, toStreamD)
18+import Streamly.Internal.Data.Stream.Type (Stream, fromStreamK, toStreamK)
3319
34−import qualified Streamly.Internal.Data.Stream.StreamD as D
3520import qualified Streamly.Internal.Data.Stream.StreamK as K
3621
3722-- $setup
@@ -46,6 +31,7 @@ import qualified Streamly.Internal.Data.Stream.StreamK as K
4631--
4732-- / Internal/
4833--
34+-- /CPS/
4935{-# INLINE hoist #-}
5036hoist :: (Monad m, Monad n)
5137 => (forall x. m x -> n x) -> Stream m a -> Stream n a
@@ -55,82 +41,8 @@ hoist f xs = fromStreamK $ K.hoist f (toStreamK xs)
5541--
5642-- / Internal/
5743--
44+-- /CPS/
45+--
5846{-# INLINE generally #-}
5947generally :: Monad m => Stream Identity a -> Stream m a
6048generally xs = fromStreamK $ K.hoist (return . runIdentity) (toStreamK xs)
61−
62−------------------------------------------------------------------------------
63−-- Add and remove a monad transformer
64−------------------------------------------------------------------------------
65−
66−-- | Lift the inner monad @m@ of a stream @Stream m a@ to @tr m@ using the monad
67−-- transformer @tr@.
68−--
69−{-# INLINE liftInner #-}
70−liftInner :: (Monad m, MonadTrans tr, Monad (tr m))
71− => Stream m a -> Stream (tr m) a
72−liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
73−
74−------------------------------------------------------------------------------
75−-- Sharing read only state in a stream
76−------------------------------------------------------------------------------
77−
78−-- | Evaluate the inner monad of a stream as 'ReaderT'.
79−--
80−{-# INLINE runReaderT #-}
81−runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
82−runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
83−
84−-- | Run a stream transformation using a given environment.
85−--
86−-- See also: 'Serial.map'
87−--
88−-- / Internal/
89−--
90−{-# INLINE usingReaderT #-}
91−usingReaderT
92− :: Monad m
93− => m r
94− -> (Stream (ReaderT r m) a -> Stream (ReaderT r m) a)
95− -> Stream m a
96− -> Stream m a
97−usingReaderT r f xs = runReaderT r $ f $ liftInner xs
98−
99−------------------------------------------------------------------------------
100−-- Sharing read write state in a stream
101−------------------------------------------------------------------------------
102−
103−-- | Evaluate the inner monad of a stream as 'StateT'.
104−--
105−-- >>> evalStateT s = fmap snd . Stream.runStateT s
106−--
107−-- / Internal/
108−--
109−{-# INLINE evalStateT #-}
110−evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
111−-- evalStateT s = fmap snd . runStateT s
112−evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
113−
114−-- | Run a stateful (StateT) stream transformation using a given state.
115−--
116−-- >>> usingStateT s f = Stream.evalStateT s . f . Stream.liftInner
117−--
118−-- See also: 'scan'
119−--
120−-- / Internal/
121−--
122−{-# INLINE usingStateT #-}
123−usingStateT
124− :: Monad m
125− => m s
126− -> (Stream (StateT s m) a -> Stream (StateT s m) a)
127− -> Stream m a
128− -> Stream m a
129−usingStateT s f = evalStateT s . f . liftInner
130−
131−-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
132−-- state and value pair after each step.
133−--
134−{-# INLINE runStateT #-}
135−runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
136−runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
core/src/Streamly/Internal/Data/Stream/StreamD.hs+2
@@ -22,6 +22,7 @@ module Streamly.Internal.Data.Stream.StreamD
2222 , module Streamly.Internal.Data.Stream.StreamD.Eliminate
2323 , module Streamly.Internal.Data.Stream.StreamD.Exception
2424 , module Streamly.Internal.Data.Stream.StreamD.Lift
25+ , module Streamly.Internal.Data.Stream.StreamD.Transformer
2526 , module Streamly.Internal.Data.Stream.StreamD.Nesting
2627 , module Streamly.Internal.Data.Stream.StreamD.Transform
2728 )
@@ -32,5 +33,6 @@ import Streamly.Internal.Data.Stream.StreamD.Generate
3233import Streamly.Internal.Data.Stream.StreamD.Eliminate
3334import Streamly.Internal.Data.Stream.StreamD.Exception
3435import Streamly.Internal.Data.Stream.StreamD.Lift
36+import Streamly.Internal.Data.Stream.StreamD.Transformer
3537import Streamly.Internal.Data.Stream.StreamD.Nesting
3638import Streamly.Internal.Data.Stream.StreamD.Transform
core/src/Streamly/Internal/Data/Stream/StreamD/Lift.hs−68
@@ -13,26 +13,14 @@ module Streamly.Internal.Data.Stream.StreamD.Lift
1313 -- * Generalize Inner Monad
1414 hoist
1515 , generally -- XXX generalize
16−
17− -- * Transform Inner Monad
18− , liftInner
19− , runReaderT
20− , evalStateT
21− , runStateT
2216 )
2317where
2418
2519#include "inline.hs"
2620
27−import Control.Monad.Trans.Class (MonadTrans(lift))
28−import Control.Monad.Trans.Reader (ReaderT)
29−import Control.Monad.Trans.State.Strict (StateT)
3021import Data.Functor.Identity (Identity(..))
3122import Streamly.Internal.Data.SVar.Type (adaptState)
3223
33−import qualified Control.Monad.Trans.Reader as Reader
34−import qualified Control.Monad.Trans.State.Strict as State
35−
3624import Streamly.Internal.Data.Stream.StreamD.Type
3725
3826-------------------------------------------------------------------------------
@@ -54,59 +42,3 @@ hoist f (Stream step state) = Stream step' state
5442{-# INLINE generally #-}
5543generally :: Monad m => Stream Identity a -> Stream m a
5644generally = hoist (return . runIdentity)
57−
58−-------------------------------------------------------------------------------
59−-- Transform Inner Monad
60−-------------------------------------------------------------------------------
61−
62−{-# INLINE_NORMAL liftInner #-}
63−liftInner :: (Monad m, MonadTrans t, Monad (t m))
64− => Stream m a -> Stream (t m) a
65−liftInner (Stream step state) = Stream step' state
66− where
67− {-# INLINE_LATE step' #-}
68− step' gst st = do
69− r <- lift $ step (adaptState gst) st
70− return $ case r of
71− Yield x s -> Yield x s
72− Skip s -> Skip s
73− Stop -> Stop
74−
75−{-# INLINE_NORMAL runReaderT #-}
76−runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
77−runReaderT env (Stream step state) = Stream step' (state, env)
78− where
79− {-# INLINE_LATE step' #-}
80− step' gst (st, action) = do
81− sv <- action
82− r <- Reader.runReaderT (step (adaptState gst) st) sv
83− return $ case r of
84− Yield x s -> Yield x (s, return sv)
85− Skip s -> Skip (s, return sv)
86− Stop -> Stop
87−
88−{-# INLINE_NORMAL evalStateT #-}
89−evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
90−evalStateT initial (Stream step state) = Stream step' (state, initial)
91− where
92− {-# INLINE_LATE step' #-}
93− step' gst (st, action) = do
94− sv <- action
95− (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
96− return $ case r of
97− Yield x s -> Yield x (s, return sv')
98− Skip s -> Skip (s, return sv')
99− Stop -> Stop
100−
101−{-# INLINE_NORMAL runStateT #-}
102−runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
103−runStateT initial (Stream step state) = Stream step' (state, initial)
104− where
105− {-# INLINE_LATE step' #-}
106− step' gst (st, action) = do
107− sv <- action
108− (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
109− return $ case r of
110− Yield x s -> Yield (sv', x) (s, return sv')
111− Skip s -> Skip (s, return sv')
112− Stop -> Stop
core/src/Streamly/Internal/Data/Stream/StreamD/Transformer.hsnew file+87
@@ -0,0 +1,87 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Transformer
3+-- Copyright : (c) 2018 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+-- Transform the underlying monad of a stream using a monad transfomer.
10+
11+module Streamly.Internal.Data.Stream.StreamD.Transformer
12+ (
13+ -- * Transform Inner Monad
14+ liftInner
15+ , runReaderT
16+ , evalStateT
17+ , runStateT
18+ )
19+where
20+
21+#include "inline.hs"
22+
23+import Control.Monad.Trans.Class (MonadTrans(lift))
24+import Control.Monad.Trans.Reader (ReaderT)
25+import Control.Monad.Trans.State.Strict (StateT)
26+import Streamly.Internal.Data.SVar.Type (adaptState)
27+
28+import qualified Control.Monad.Trans.Reader as Reader
29+import qualified Control.Monad.Trans.State.Strict as State
30+
31+import Streamly.Internal.Data.Stream.StreamD.Type
32+
33+-------------------------------------------------------------------------------
34+-- Transform Inner Monad
35+-------------------------------------------------------------------------------
36+
37+{-# INLINE_NORMAL liftInner #-}
38+liftInner :: (Monad m, MonadTrans t, Monad (t m))
39+ => Stream m a -> Stream (t m) a
40+liftInner (Stream step state) = Stream step' state
41+ where
42+ {-# INLINE_LATE step' #-}
43+ step' gst st = do
44+ r <- lift $ step (adaptState gst) st
45+ return $ case r of
46+ Yield x s -> Yield x s
47+ Skip s -> Skip s
48+ Stop -> Stop
49+
50+{-# INLINE_NORMAL runReaderT #-}
51+runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
52+runReaderT env (Stream step state) = Stream step' (state, env)
53+ where
54+ {-# INLINE_LATE step' #-}
55+ step' gst (st, action) = do
56+ sv <- action
57+ r <- Reader.runReaderT (step (adaptState gst) st) sv
58+ return $ case r of
59+ Yield x s -> Yield x (s, return sv)
60+ Skip s -> Skip (s, return sv)
61+ Stop -> Stop
62+
63+{-# INLINE_NORMAL evalStateT #-}
64+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
65+evalStateT initial (Stream step state) = Stream step' (state, initial)
66+ where
67+ {-# INLINE_LATE step' #-}
68+ step' gst (st, action) = do
69+ sv <- action
70+ (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
71+ return $ case r of
72+ Yield x s -> Yield x (s, return sv')
73+ Skip s -> Skip (s, return sv')
74+ Stop -> Stop
75+
76+{-# INLINE_NORMAL runStateT #-}
77+runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
78+runStateT initial (Stream step state) = Stream step' (state, initial)
79+ where
80+ {-# INLINE_LATE step' #-}
81+ step' gst (st, action) = do
82+ sv <- action
83+ (r, !sv') <- State.runStateT (step (adaptState gst) st) sv
84+ return $ case r of
85+ Yield x s -> Yield (sv', x) (s, return sv')
86+ Skip s -> Skip (s, return sv')
87+ Stop -> Stop
core/src/Streamly/Internal/Data/Stream/StreamK/Transformer.hsnew file+52
@@ -0,0 +1,52 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamK.Transformer
3+-- Copyright : (c) 2017 Composewell Technologies
4+-- License : BSD3
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+module Streamly.Internal.Data.Stream.StreamK.Transformer
10+ (
11+ liftInner
12+ , evalStateT
13+ )
14+where
15+
16+import Control.Monad.Trans.Class (MonadTrans(lift))
17+import Control.Monad.Trans.State.Strict (StateT)
18+import Streamly.Internal.Data.Stream.StreamK
19+ (Stream, nil, cons, uncons, fromEffect)
20+
21+import qualified Control.Monad.Trans.State.Strict as State
22+
23+------------------------------------------------------------------------------
24+-- Lifting inner monad
25+------------------------------------------------------------------------------
26+
27+{-# INLINE evalStateT #-}
28+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
29+evalStateT = go
30+
31+ where
32+
33+ -- XXX Do not use stream monad
34+ go st m1 = do
35+ (res, s1) <- lift $ st >>= State.runStateT (uncons m1)
36+ case res of
37+ Just (h, t) -> cons h (go (return s1) t)
38+ Nothing -> nil
39+
40+{-# INLINE liftInner #-}
41+liftInner :: (Monad m, MonadTrans t, Monad (t m)) =>
42+ Stream m a -> Stream (t m) a
43+liftInner = go
44+
45+ where
46+
47+ -- XXX Do not use stream monad
48+ go m1 = do
49+ res <- fromEffect $ lift $ uncons m1
50+ case res of
51+ Just (h, t) -> cons h (go t)
52+ Nothing -> nil
core/src/Streamly/Internal/Data/Stream/Top.hs+1−1
@@ -57,7 +57,7 @@ import qualified Streamly.Internal.Data.Array.Generic as Array
5757import qualified Streamly.Internal.Data.Array.Mut.Type as MA
5858import qualified Streamly.Internal.Data.Fold as Fold
5959import qualified Streamly.Internal.Data.Parser as Parser
60−import qualified Streamly.Internal.Data.Stream.Lift as Stream
60+import qualified Streamly.Internal.Data.Stream.Transformer as Stream
6161import qualified Streamly.Internal.Data.Stream.Eliminate as Stream
6262import qualified Streamly.Internal.Data.Stream.Generate as Stream
6363import qualified Streamly.Internal.Data.Stream.Expand as Stream
core/src/Streamly/Internal/Data/Stream/Transformer.hsnew file+105
@@ -0,0 +1,105 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.Transformer
3+-- Copyright : (c) 2019 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.Transformer
10+ (
11+ liftInner
12+ , usingReaderT
13+ , runReaderT
14+ , evalStateT
15+ , usingStateT
16+ , runStateT
17+ )
18+where
19+
20+import Control.Monad.Trans.Reader (ReaderT)
21+import Control.Monad.Trans.State.Strict (StateT)
22+import Control.Monad.Trans.Class (MonadTrans(..))
23+import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
24+
25+import qualified Streamly.Internal.Data.Stream.StreamD.Transformer as D
26+
27+-- $setup
28+-- >>> :m
29+-- >>> import Streamly.Internal.Data.Stream as Stream
30+
31+------------------------------------------------------------------------------
32+-- Add and remove a monad transformer
33+------------------------------------------------------------------------------
34+
35+-- | Lift the inner monad @m@ of a stream @Stream m a@ to @tr m@ using the monad
36+-- transformer @tr@.
37+--
38+{-# INLINE liftInner #-}
39+liftInner :: (Monad m, MonadTrans tr, Monad (tr m))
40+ => Stream m a -> Stream (tr m) a
41+liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
42+
43+------------------------------------------------------------------------------
44+-- Sharing read only state in a stream
45+------------------------------------------------------------------------------
46+
47+-- | Evaluate the inner monad of a stream as 'ReaderT'.
48+--
49+{-# INLINE runReaderT #-}
50+runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
51+runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
52+
53+-- | Run a stream transformation using a given environment.
54+--
55+-- See also: 'Serial.map'
56+--
57+-- / Internal/
58+--
59+{-# INLINE usingReaderT #-}
60+usingReaderT
61+ :: Monad m
62+ => m r
63+ -> (Stream (ReaderT r m) a -> Stream (ReaderT r m) a)
64+ -> Stream m a
65+ -> Stream m a
66+usingReaderT r f xs = runReaderT r $ f $ liftInner xs
67+
68+------------------------------------------------------------------------------
69+-- Sharing read write state in a stream
70+------------------------------------------------------------------------------
71+
72+-- | Evaluate the inner monad of a stream as 'StateT'.
73+--
74+-- >>> evalStateT s = fmap snd . Stream.runStateT s
75+--
76+-- / Internal/
77+--
78+{-# INLINE evalStateT #-}
79+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
80+-- evalStateT s = fmap snd . runStateT s
81+evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
82+
83+-- | Run a stateful (StateT) stream transformation using a given state.
84+--
85+-- >>> usingStateT s f = Stream.evalStateT s . f . Stream.liftInner
86+--
87+-- See also: 'scan'
88+--
89+-- / Internal/
90+--
91+{-# INLINE usingStateT #-}
92+usingStateT
93+ :: Monad m
94+ => m s
95+ -> (Stream (StateT s m) a -> Stream (StateT s m) a)
96+ -> Stream m a
97+ -> Stream m a
98+usingStateT s f = evalStateT s . f . liftInner
99+
100+-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
101+-- state and value pair after each step.
102+--
103+{-# INLINE runStateT #-}
104+runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
105+runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
core/streamly-core.cabal+3
@@ -286,6 +286,7 @@ library
286286 , Streamly.Internal.Data.Stream.StreamD.Transform
287287 , Streamly.Internal.Data.Stream.StreamD.Exception
288288 , Streamly.Internal.Data.Stream.StreamD.Lift
289+ , Streamly.Internal.Data.Stream.StreamD.Transformer
289290 , Streamly.Internal.Data.Stream.StreamD
290291 , Streamly.Internal.Data.Stream.Common
291292
@@ -312,6 +313,7 @@ library
312313 , Streamly.Internal.Data.Stream.Exception
313314 , Streamly.Internal.Data.Stream.Expand
314315 , Streamly.Internal.Data.Stream.Lift
316+ , Streamly.Internal.Data.Stream.Transformer
315317 , Streamly.Internal.Data.Stream.Reduce
316318 , Streamly.Internal.Data.Stream.Top
317319 , Streamly.Internal.Data.Stream
@@ -344,6 +346,7 @@ library
344346 , Streamly.Internal.Data.Ring
345347
346348 -- Only used for benchmarks
349+ , Streamly.Internal.Data.Stream.StreamK.Transformer
347350 , Streamly.Internal.Data.Stream.StreamK
348351
349352 -- streamly-console