on master help sign in
Move foldrT/foldlT to transformer module
3c10a1fHarendra Kumar
core/src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+1−17
@@ -30,9 +30,7 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
30
30
31 -- * Folding
31 -- * Folding
32 , foldrS
32 , foldrS
33− , foldrT
34 , foldlS
33 , foldlS
35− , foldlT
36
34
37 -- * Scanning By 'Fold'
35 -- * Scanning By 'Fold'
38 , postscanOnce -- XXX rename to postscan
36 , postscanOnce -- XXX rename to postscan
@@ -123,14 +121,12 @@ where
123#include "inline.hs"
121#include "inline.hs"
124
122
125import Control.Monad (void)
123import Control.Monad (void)
126−import Control.Monad.Trans.Class (MonadTrans(lift))
127import Data.Maybe (fromJust, isJust)
124import Data.Maybe (fromJust, isJust)
128import Fusion.Plugin.Types (Fuse(..))
125import Fusion.Plugin.Types (Fuse(..))
129−import GHC.Types (SPEC(..))
130
126
131import Streamly.Internal.Data.Fold.Type (Fold(..))
127import Streamly.Internal.Data.Fold.Type (Fold(..))
132import Streamly.Internal.Data.Pipe.Type (Pipe(..), PipeState(..))
128import Streamly.Internal.Data.Pipe.Type (Pipe(..), PipeState(..))
133−import Streamly.Internal.Data.SVar.Type (defState, adaptState)
129+import Streamly.Internal.Data.SVar.Type (adaptState)
134
130
135import qualified Streamly.Internal.Data.Fold.Type as FL
131import qualified Streamly.Internal.Data.Fold.Type as FL
136import qualified Streamly.Internal.Data.Pipe.Type as Pipe
132import qualified Streamly.Internal.Data.Pipe.Type as Pipe
@@ -175,18 +171,6 @@ transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
175-- Transformation Folds
171-- Transformation Folds
176------------------------------------------------------------------------------
172------------------------------------------------------------------------------
177
173
178−{-# INLINE_NORMAL foldlT #-}
179−foldlT :: (Monad m, Monad (s m), MonadTrans s)
180− => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
181−foldlT fstep begin (Stream step state) = go SPEC begin state
182− where
183− go !_ acc st = do
184− r <- lift $ step defState st
185− case r of
186− Yield x s -> go SPEC (fstep acc x) s
187− Skip s -> go SPEC acc s
188− Stop -> acc
189−
190-- Note, this is going to have horrible performance, because of the nature of
174-- Note, this is going to have horrible performance, because of the nature of
191-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
175-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
192-- likely be practically unusable.
176-- likely be practically unusable.
core/src/Streamly/Internal/Data/Stream/StreamD/Transformer.hs+34−2
@@ -10,8 +10,11 @@
10
10
11module Streamly.Internal.Data.Stream.StreamD.Transformer
11module Streamly.Internal.Data.Stream.StreamD.Transformer
12 (
12 (
13+ foldlT
14+ , foldrT
15+
13 -- * Transform Inner Monad
16 -- * Transform Inner Monad
14− liftInner
17+ , liftInner
15 , runReaderT
18 , runReaderT
16 , evalStateT
19 , evalStateT
17 , runStateT
20 , runStateT
@@ -23,13 +26,42 @@ where
23import Control.Monad.Trans.Class (MonadTrans(lift))
26import Control.Monad.Trans.Class (MonadTrans(lift))
24import Control.Monad.Trans.Reader (ReaderT)
27import Control.Monad.Trans.Reader (ReaderT)
25import Control.Monad.Trans.State.Strict (StateT)
28import Control.Monad.Trans.State.Strict (StateT)
29+import GHC.Types (SPEC(..))
26−import Streamly.Internal.Data.SVar.Type (adaptState)
30+import Streamly.Internal.Data.SVar.Type (defState, adaptState)
27
31
28import qualified Control.Monad.Trans.Reader as Reader
32import qualified Control.Monad.Trans.Reader as Reader
29import qualified Control.Monad.Trans.State.Strict as State
33import qualified Control.Monad.Trans.State.Strict as State
30
34
31import Streamly.Internal.Data.Stream.StreamD.Type
35import Streamly.Internal.Data.Stream.StreamD.Type
32
36
37+{-# INLINE_NORMAL foldlT #-}
38+foldlT :: (Monad m, Monad (s m), MonadTrans s)
39+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
40+foldlT fstep begin (Stream step state) = go SPEC begin state
41+ where
42+ go !_ acc st = do
43+ r <- lift $ step defState st
44+ case r of
45+ Yield x s -> go SPEC (fstep acc x) s
46+ Skip s -> go SPEC acc s
47+ Stop -> acc
48+
49+-- Right fold to some transformer (T) monad. This can be useful to implement
50+-- stateless combinators like map, filtering, insertions, takeWhile, dropWhile.
51+--
52+{-# INLINE_NORMAL foldrT #-}
53+foldrT :: (Monad m, Monad (t m), MonadTrans t)
54+ => (a -> t m b -> t m b) -> t m b -> Stream m a -> t m b
55+foldrT f final (Stream step state) = go SPEC state
56+ where
57+ {-# INLINE_LATE go #-}
58+ go !_ st = do
59+ r <- lift $ step defState st
60+ case r of
61+ Yield x s -> f x (go SPEC s)
62+ Skip s -> go SPEC s
63+ Stop -> final
64+
33-------------------------------------------------------------------------------
65-------------------------------------------------------------------------------
34-- Transform Inner Monad
66-- Transform Inner Monad
35-------------------------------------------------------------------------------
67-------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/StreamD/Type.hs−17
@@ -47,7 +47,6 @@ module Streamly.Internal.Data.Stream.StreamD.Type
47 , foldEither
47 , foldEither
48
48
49 -- * Right Folds
49 -- * Right Folds
50− , foldrT
51 , foldrM
50 , foldrM
52 , foldrMx
51 , foldrMx
53 , foldr
52 , foldr
@@ -430,22 +429,6 @@ foldrS f final (Stream step state) = go SPEC state
430 Skip s -> go SPEC s
429 Skip s -> go SPEC s
431 Stop -> final
430 Stop -> final
432
431
433−-- Right fold to some transformer (T) monad. This can be useful to implement
434−-- stateless combinators like map, filtering, insertions, takeWhile, dropWhile.
435−--
436−{-# INLINE_NORMAL foldrT #-}
437−foldrT :: (Monad m, Monad (t m), MonadTrans t)
438− => (a -> t m b -> t m b) -> t m b -> Stream m a -> t m b
439−foldrT f final (Stream step state) = go SPEC state
440− where
441− {-# INLINE_LATE go #-}
442− go !_ st = do
443− r <- lift $ step defState st
444− case r of
445− Yield x s -> f x (go SPEC s)
446− Skip s -> go SPEC s
447− Stop -> final
448−
449------------------------------------------------------------------------------
432------------------------------------------------------------------------------
450-- Left Folds
433-- Left Folds
451------------------------------------------------------------------------------
434------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/StreamK.hs−27
@@ -73,12 +73,10 @@ module Streamly.Internal.Data.Stream.StreamK
73 , foldr
73 , foldr
74 , foldr1
74 , foldr1
75 , foldrM
75 , foldrM
76− , foldrT
77
76
78 , foldl'
77 , foldl'
79 , foldlM'
78 , foldlM'
80 , foldlS
79 , foldlS
81− , foldlT
82 , foldlx'
80 , foldlx'
83 , foldlMx'
81 , foldlMx'
84 , fold
82 , fold
@@ -178,7 +176,6 @@ where
178#include "assert.hs"
176#include "assert.hs"
179
177
180import Control.Monad.Catch (MonadThrow, throwM)
178import Control.Monad.Catch (MonadThrow, throwM)
181−import Control.Monad.Trans.Class (MonadTrans(lift))
182import Control.Monad (void, join)
179import Control.Monad (void, join)
183import Streamly.Internal.Data.Fold.Type (Fold(..))
180import Streamly.Internal.Data.Fold.Type (Fold(..))
184import Streamly.Internal.Data.SVar.Type (adaptState, defState)
181import Streamly.Internal.Data.SVar.Type (adaptState, defState)
@@ -274,18 +271,6 @@ fromList = fromFoldable
274foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
271foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
275foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
272foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
276
273
277−-- | Right associative fold to an arbitrary transformer monad.
278−{-# INLINE foldrT #-}
279−foldrT :: (Monad m, Monad (s m), MonadTrans s)
280− => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
281−foldrT step final = go
282− where
283− go m1 = do
284− res <- lift $ uncons m1
285− case res of
286− Just (h, t) -> step h (go t)
287− Nothing -> final
288−
289{-# INLINE foldr1 #-}
274{-# INLINE foldr1 #-}
290foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
275foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
291foldr1 step m = do
276foldr1 step m = do
@@ -379,18 +364,6 @@ foldBreak fld strm = do
379foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
364foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
380foldlM' step begin = foldlMx' step begin return
365foldlM' step begin = foldlMx' step begin return
381
366
382−-- | Lazy left fold to an arbitrary transformer monad.
383−{-# INLINE foldlT #-}
384−foldlT :: (Monad m, Monad (s m), MonadTrans s)
385− => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
386−foldlT step = go
387− where
388− go acc m1 = do
389− res <- lift $ uncons m1
390− case res of
391− Just (h, t) -> go (step acc h) t
392− Nothing -> acc
393−
394------------------------------------------------------------------------------
367------------------------------------------------------------------------------
395-- Specialized folds
368-- Specialized folds
396------------------------------------------------------------------------------
369------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/StreamK/Transformer.hs+28−1
@@ -8,7 +8,10 @@
8--
8--
9module Streamly.Internal.Data.Stream.StreamK.Transformer
9module Streamly.Internal.Data.Stream.StreamK.Transformer
10 (
10 (
11+ foldlT
12+ , foldrT
13+
11− liftInner
14+ , liftInner
12 , evalStateT
15 , evalStateT
13 )
16 )
14where
17where
@@ -20,6 +23,30 @@ import Streamly.Internal.Data.Stream.StreamK
20
23
21import qualified Control.Monad.Trans.State.Strict as State
24import qualified Control.Monad.Trans.State.Strict as State
22
25
26+-- | Lazy left fold to an arbitrary transformer monad.
27+{-# INLINE foldlT #-}
28+foldlT :: (Monad m, Monad (s m), MonadTrans s)
29+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
30+foldlT step = go
31+ where
32+ go acc m1 = do
33+ res <- lift $ uncons m1
34+ case res of
35+ Just (h, t) -> go (step acc h) t
36+ Nothing -> acc
37+
38+-- | Right associative fold to an arbitrary transformer monad.
39+{-# INLINE foldrT #-}
40+foldrT :: (Monad m, Monad (s m), MonadTrans s)
41+ => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
42+foldrT step final = go
43+ where
44+ go m1 = do
45+ res <- lift $ uncons m1
46+ case res of
47+ Just (h, t) -> step h (go t)
48+ Nothing -> final
49+
23------------------------------------------------------------------------------
50------------------------------------------------------------------------------
24-- Lifting inner monad
51-- Lifting inner monad
25------------------------------------------------------------------------------
52------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/Transform.hs−20
@@ -14,7 +14,6 @@ module Streamly.Internal.Data.Stream.Transform
14
14
15 -- * Folding
15 -- * Folding
16 , foldrS
16 , foldrS
17− , foldrT
18
17
19 -- * Mapping
18 -- * Mapping
20 -- | Stateless one-to-one maps.
19 -- | Stateless one-to-one maps.
@@ -144,7 +143,6 @@ where
144import Control.Concurrent (threadDelay)
143import Control.Concurrent (threadDelay)
145import Control.Monad (void)
144import Control.Monad (void)
146import Control.Monad.IO.Class (MonadIO (liftIO))
145import Control.Monad.IO.Class (MonadIO (liftIO))
147−import Control.Monad.Trans.Class (MonadTrans(..))
148import Data.Either (fromLeft, isLeft, isRight, fromRight)
146import Data.Either (fromLeft, isLeft, isRight, fromRight)
149import Data.Maybe (isJust, fromJust)
147import Data.Maybe (isJust, fromJust)
150
148
@@ -248,24 +246,6 @@ foldrS f z xs =
248 (toStreamK z)
246 (toStreamK z)
249 (toStreamK xs)
247 (toStreamK xs)
250
248
251−-- | Right fold to a transformer monad. This is the most general right fold
252−-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
253−-- implementation can be more efficient:
254−--
255−-- >>> foldrS = foldrT
256−--
257−-- >>> step f x xs = lift $ f x (runIdentityT xs)
258−-- >>> foldrM f z s = runIdentityT $ foldrT (step f) (lift z) s
259−--
260−-- 'foldrT' can be used to translate streamly streams to other transformer
261−-- monads e.g. to a different streaming type.
262−--
263−-- /Pre-release/
264−{-# INLINE foldrT #-}
265−foldrT :: (Monad m, Monad (s m), MonadTrans s)
266− => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
267−foldrT f z s = D.foldrT f z (toStreamD s)
268−
269------------------------------------------------------------------------------
249------------------------------------------------------------------------------
270-- Transformation by Mapping
250-- Transformation by Mapping
271------------------------------------------------------------------------------
251------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Stream/Transformer.hs+25−3
@@ -8,7 +8,9 @@
8
8
9module Streamly.Internal.Data.Stream.Transformer
9module Streamly.Internal.Data.Stream.Transformer
10 (
10 (
11+ foldrT
12+
11− liftInner
13+ , liftInner
12 , usingReaderT
14 , usingReaderT
13 , runReaderT
15 , runReaderT
14 , evalStateT
16 , evalStateT
@@ -17,16 +19,36 @@ module Streamly.Internal.Data.Stream.Transformer
17 )
19 )
18where
20where
19
21
22+import Control.Monad.Trans.Class (MonadTrans)
20import Control.Monad.Trans.Reader (ReaderT)
23import Control.Monad.Trans.Reader (ReaderT)
21import Control.Monad.Trans.State.Strict (StateT)
24import Control.Monad.Trans.State.Strict (StateT)
22−import Control.Monad.Trans.Class (MonadTrans(..))
23import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
25import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
24
26
25import qualified Streamly.Internal.Data.Stream.StreamD.Transformer as D
27import qualified Streamly.Internal.Data.Stream.StreamD.Transformer as D
26
28
27-- $setup
29-- $setup
28-- >>> :m
30-- >>> :m
31+-- >>> import Control.Monad.Trans (lift)
32+-- >>> import Control.Monad.Trans.Identity (runIdentityT)
29−-- >>> import Streamly.Internal.Data.Stream as Stream
33+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
34+
35+-- | Right fold to a transformer monad. This is the most general right fold
36+-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
37+-- implementation can be more efficient:
38+--
39+-- >>> foldrS = Stream.foldrT
40+--
41+-- >>> step f x xs = lift $ f x (runIdentityT xs)
42+-- >>> foldrM f z s = runIdentityT $ Stream.foldrT (step f) (lift z) s
43+--
44+-- 'foldrT' can be used to translate streamly streams to other transformer
45+-- monads e.g. to a different streaming type.
46+--
47+-- /Pre-release/
48+{-# INLINE foldrT #-}
49+foldrT :: (Monad m, Monad (s m), MonadTrans s)
50+ => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
51+foldrT f z s = D.foldrT f z (toStreamD s)
30
52
31------------------------------------------------------------------------------
53------------------------------------------------------------------------------
32-- Add and remove a monad transformer
54-- Add and remove a monad transformer