on master help sign in
Add generic inner monad lifting ops
1349b8cHarendra Kumar
core/src/Streamly/Internal/Data/Stream/Bottom.hs+4−6
@@ -89,17 +89,15 @@ import Streamly.Internal.Data.Stream.Type
89-- $setup
89-- $setup
90-- >>> :m
90-- >>> :m
91-- >>> import Control.Monad (join, (>=>), (<=<))
91-- >>> import Control.Monad (join, (>=>), (<=<))
92−-- >>> import Control.Monad.Trans.Class (lift)
93-- >>> import Data.Function (fix, (&))
92-- >>> import Data.Function (fix, (&))
94-- >>> import Data.Maybe (fromJust, isJust)
93-- >>> import Data.Maybe (fromJust, isJust)
95−-- >>> import Data.Semigroup (cycle1)
96-- >>> import Prelude hiding (take, takeWhile, drop, reverse)
94-- >>> import Prelude hiding (take, takeWhile, drop, reverse)
97-- >>> import System.IO.Unsafe (unsafePerformIO)
95-- >>> import System.IO.Unsafe (unsafePerformIO)
98−-- >>> import Streamly.Internal.Data.Stream as Stream
99-- >>> import qualified Streamly.Data.Array as Array
96-- >>> import qualified Streamly.Data.Array as Array
100−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
97+-- >>> import qualified Streamly.Data.Fold as Fold
101−-- >>> import qualified Streamly.Internal.Data.Parser as Parser
98+-- >>> import qualified Streamly.Data.Parser as Parser
102−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
99+-- >>> import qualified Streamly.Data.Unfold as Unfold
100+-- >>> import Streamly.Internal.Data.Stream as Stream
103
101
104------------------------------------------------------------------------------
102------------------------------------------------------------------------------
105-- Generation - Time related
103-- Generation - Time related
core/src/Streamly/Internal/Data/Stream/Lift.hs+40−1
@@ -11,12 +11,19 @@ module Streamly.Internal.Data.Stream.Lift
11 -- * Generalize Inner Monad
11 -- * Generalize Inner Monad
12 hoist
12 hoist
13 , generally
13 , generally
14+
15+ -- * Transform Inner Monad
16+ , liftInnerWith
17+ , runInnerWith
18+ , runInnerWithState
14 )
19 )
15where
20where
16
21
17import Data.Functor.Identity (Identity (..))
22import Data.Functor.Identity (Identity (..))
18−import Streamly.Internal.Data.Stream.Type (Stream, fromStreamK, toStreamK)
23+import Streamly.Internal.Data.Stream.Type
24+ (Stream, fromStreamD, toStreamD, fromStreamK, toStreamK)
19
25
26+import qualified Streamly.Internal.Data.Stream.StreamD as D
20import qualified Streamly.Internal.Data.Stream.StreamK as K
27import qualified Streamly.Internal.Data.Stream.StreamK as K
21
28
22-- $setup
29-- $setup
@@ -46,3 +53,35 @@ hoist f xs = fromStreamK $ K.hoist f (toStreamK xs)
46{-# INLINE generally #-}
53{-# INLINE generally #-}
47generally :: Monad m => Stream Identity a -> Stream m a
54generally :: Monad m => Stream Identity a -> Stream m a
48generally xs = fromStreamK $ K.hoist (return . runIdentity) (toStreamK xs)
55generally xs = fromStreamK $ K.hoist (return . runIdentity) (toStreamK xs)
56+
57+------------------------------------------------------------------------------
58+-- Add and remove a monad transformer
59+------------------------------------------------------------------------------
60+
61+-- | Lift the inner monad @m@ of a stream @Stream m a@ to @t m@ using the
62+-- supplied lift function.
63+--
64+{-# INLINE liftInnerWith #-}
65+liftInnerWith :: (Monad m, Monad (t m))
66+ => (forall b. m b -> t m b) -> Stream m a -> Stream (t m) a
67+liftInnerWith lift xs = fromStreamD $ D.liftInnerWith lift (toStreamD xs)
68+
69+-- | Evaluate the inner monad of a stream using the supplied runner function.
70+--
71+{-# INLINE runInnerWith #-}
72+runInnerWith :: (Monad m, Applicative (t m)) =>
73+ (forall b. t m b -> m b) -> Stream (t m) a -> Stream m a
74+runInnerWith run xs = fromStreamD $ D.runInnerWith run (toStreamD xs)
75+
76+-- | Evaluate the inner monad of a stream using the supplied stateful runner
77+-- function and the initial state. The state returned by an invocation of the
78+-- runner is supplied as input state to the next invocation.
79+--
80+{-# INLINE runInnerWithState #-}
81+runInnerWithState :: (Monad m, Applicative (t m)) =>
82+ (forall b. s -> t m b -> m (b, s))
83+ -> m s
84+ -> Stream (t m) a
85+ -> Stream m (s, a)
86+runInnerWithState run initial xs =
87+ fromStreamD $ D.runInnerWithState run initial (toStreamD xs)
core/src/Streamly/Internal/Data/Stream/StreamD/Lift.hs+59
@@ -13,6 +13,11 @@ module Streamly.Internal.Data.Stream.StreamD.Lift
13 -- * Generalize Inner Monad
13 -- * Generalize Inner Monad
14 hoist
14 hoist
15 , generally -- XXX generalize
15 , generally -- XXX generalize
16+
17+ -- * Transform Inner Monad
18+ , liftInnerWith
19+ , runInnerWith
20+ , runInnerWithState
16 )
21 )
17where
22where
18
23
@@ -42,3 +47,57 @@ hoist f (Stream step state) = Stream step' state
42{-# INLINE generally #-}
47{-# INLINE generally #-}
43generally :: Monad m => Stream Identity a -> Stream m a
48generally :: Monad m => Stream Identity a -> Stream m a
44generally = hoist (return . runIdentity)
49generally = hoist (return . runIdentity)
50+
51+-------------------------------------------------------------------------------
52+-- Transform Inner Monad
53+-------------------------------------------------------------------------------
54+
55+{-# INLINE_NORMAL liftInnerWith #-}
56+liftInnerWith :: (Monad (t m)) =>
57+ (forall b. m b -> t m b) -> Stream m a -> Stream (t m) a
58+liftInnerWith lift (Stream step state) = Stream step1 state
59+
60+ where
61+
62+ {-# INLINE_LATE step1 #-}
63+ step1 gst st = do
64+ r <- lift $ step (adaptState gst) st
65+ return $ case r of
66+ Yield x s -> Yield x s
67+ Skip s -> Skip s
68+ Stop -> Stop
69+
70+{-# INLINE_NORMAL runInnerWith #-}
71+runInnerWith :: Monad m =>
72+ (forall b. t m b -> m b) -> Stream (t m) a -> Stream m a
73+runInnerWith run (Stream step state) = Stream step1 state
74+
75+ where
76+
77+ {-# INLINE_LATE step1 #-}
78+ step1 gst st = do
79+ r <- run $ step (adaptState gst) st
80+ return $ case r of
81+ Yield x s -> Yield x s
82+ Skip s -> Skip s
83+ Stop -> Stop
84+
85+{-# INLINE_NORMAL runInnerWithState #-}
86+runInnerWithState :: Monad m =>
87+ (forall b. s -> t m b -> m (b, s))
88+ -> m s
89+ -> Stream (t m) a
90+ -> Stream m (s, a)
91+runInnerWithState run initial (Stream step state) =
92+ Stream step1 (state, initial)
93+
94+ where
95+
96+ {-# INLINE_LATE step1 #-}
97+ step1 gst (st, action) = do
98+ sv <- action
99+ (r, !sv1) <- run sv (step (adaptState gst) st)
100+ return $ case r of
101+ Yield x s -> Yield (sv1, x) (s, return sv1)
102+ Skip s -> Skip (s, return sv1)
103+ Stop -> Stop
core/src/Streamly/Internal/Data/Stream/Transform.hs+5−7
@@ -167,20 +167,18 @@ import Prelude hiding
167--
167--
168-- $setup
168-- $setup
169-- >>> :m
169-- >>> :m
170−-- >>> :set -package mtl
171-- >>> import Control.Concurrent (threadDelay)
170-- >>> import Control.Concurrent (threadDelay)
172-- >>> import Control.Monad.IO.Class (MonadIO (liftIO))
171-- >>> import Control.Monad.IO.Class (MonadIO (liftIO))
173−-- >>> import Control.Monad.Trans (lift)
174−-- >>> import Control.Monad.Trans.Identity (runIdentityT)
175-- >>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
172-- >>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
176-- >>> import Data.Function ((&))
173-- >>> import Data.Function ((&))
177-- >>> import Data.Maybe (fromJust, isJust)
174-- >>> import Data.Maybe (fromJust, isJust)
178-- >>> import Prelude hiding (filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence, reverse, foldr1 , scanl, scanl1)
175-- >>> import Prelude hiding (filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence, reverse, foldr1 , scanl, scanl1)
179−-- >>> import Streamly.Internal.Data.Stream as Stream
176+-- >>> import Streamly.Internal.Data.Stream (Stream)
180-- >>> import qualified Streamly.Data.Fold as Fold
177-- >>> import qualified Streamly.Data.Fold as Fold
181−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
178+-- >>> import qualified Streamly.Data.Unfold as Unfold
179+-- >>> import qualified Streamly.Internal.Data.Fold as Fold (filtering)
182-- >>> import qualified Streamly.Internal.Data.Fold.Window as Window
180-- >>> import qualified Streamly.Internal.Data.Fold.Window as Window
183−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
181+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
184-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
182-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
185--
183--
186-- >>> hSetBuffering stdout LineBuffering
184-- >>> hSetBuffering stdout LineBuffering
@@ -693,7 +691,7 @@ intersperseBySpan _n _f _xs = undefined
693-- | Insert an effect and its output after consuming an element of a stream.
691-- | Insert an effect and its output after consuming an element of a stream.
694--
692--
695-- >>> input = Stream.fromList "hello"
693-- >>> input = Stream.fromList "hello"
696−-- >>> Stream.fold Fold.toList $ Stream.trace putChar $ intersperseSuffix (putChar '.' >> return ',') input
694+-- >>> Stream.fold Fold.toList $ Stream.trace putChar $ Stream.intersperseSuffix (putChar '.' >> return ',') input
697-- h.,e.,l.,l.,o.,"h,e,l,l,o,"
695-- h.,e.,l.,l.,o.,"h,e,l,l,o,"
698--
696--
699-- /Pre-release/
697-- /Pre-release/
core/src/Streamly/Internal/Data/Stream/Transformer.hs+1−1
@@ -29,7 +29,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD.Transformer as D
29
29
30-- $setup
30-- $setup
31-- >>> :m
31-- >>> :m
32−-- >>> import Control.Monad.Trans (lift)
32+-- >>> import Control.Monad.Trans.Class (lift)
33-- >>> import Control.Monad.Trans.Identity (runIdentityT)
33-- >>> import Control.Monad.Trans.Identity (runIdentityT)
34-- >>> import qualified Streamly.Internal.Data.Stream as Stream
34-- >>> import qualified Streamly.Internal.Data.Stream as Stream
35
35
core/streamly-core.cabal+10−11
@@ -279,6 +279,7 @@ library
279 , Streamly.Internal.Data.Array.Generic.Mut.Type
279 , Streamly.Internal.Data.Array.Generic.Mut.Type
280
280
281 -- streamly-core-streams
281 -- streamly-core-streams
282+ , Streamly.Internal.Data.Stream.StreamK
282 -- StreamD depends on streamly-array-types
283 -- StreamD depends on streamly-array-types
283 , Streamly.Internal.Data.Stream.StreamD.Generate
284 , Streamly.Internal.Data.Stream.StreamD.Generate
284 , Streamly.Internal.Data.Stream.StreamD.Eliminate
285 , Streamly.Internal.Data.Stream.StreamD.Eliminate
@@ -286,7 +287,6 @@ library
286 , Streamly.Internal.Data.Stream.StreamD.Transform
287 , Streamly.Internal.Data.Stream.StreamD.Transform
287 , Streamly.Internal.Data.Stream.StreamD.Exception
288 , Streamly.Internal.Data.Stream.StreamD.Exception
288 , Streamly.Internal.Data.Stream.StreamD.Lift
289 , Streamly.Internal.Data.Stream.StreamD.Lift
289− , Streamly.Internal.Data.Stream.StreamD.Transformer
290 , Streamly.Internal.Data.Stream.StreamD
290 , Streamly.Internal.Data.Stream.StreamD
291 , Streamly.Internal.Data.Stream.Common
291 , Streamly.Internal.Data.Stream.Common
292
292
@@ -313,9 +313,14 @@ library
313 , Streamly.Internal.Data.Stream.Exception
313 , Streamly.Internal.Data.Stream.Exception
314 , Streamly.Internal.Data.Stream.Expand
314 , Streamly.Internal.Data.Stream.Expand
315 , Streamly.Internal.Data.Stream.Lift
315 , Streamly.Internal.Data.Stream.Lift
316− , Streamly.Internal.Data.Stream.Transformer
317 , Streamly.Internal.Data.Stream.Reduce
316 , Streamly.Internal.Data.Stream.Reduce
318 , Streamly.Internal.Data.Stream.Top
317 , Streamly.Internal.Data.Stream.Top
318+
319+ -- streamly-transformers (non-base)
320+ , Streamly.Internal.Data.Stream.StreamD.Transformer
321+ , Streamly.Internal.Data.Stream.StreamK.Transformer
322+ , Streamly.Internal.Data.Stream.Transformer
323+
319 , Streamly.Internal.Data.Stream
324 , Streamly.Internal.Data.Stream
320 , Streamly.Internal.Data.Stream.Chunked
325 , Streamly.Internal.Data.Stream.Chunked
321 , Streamly.Internal.Data.Stream.Zip
326 , Streamly.Internal.Data.Stream.Zip
@@ -346,10 +351,6 @@ library
346 , Streamly.Internal.Data.Ring.Unboxed
351 , Streamly.Internal.Data.Ring.Unboxed
347 , Streamly.Internal.Data.Ring
352 , Streamly.Internal.Data.Ring
348
353
349− -- Only used for benchmarks
350− , Streamly.Internal.Data.Stream.StreamK.Transformer
351− , Streamly.Internal.Data.Stream.StreamK
352−
353 -- streamly-console
354 -- streamly-console
354 , Streamly.Internal.Console.Stdio
355 , Streamly.Internal.Console.Stdio
355
356
@@ -415,9 +416,10 @@ library
415 -- packages depending on the "ghc" package (packages
416 -- packages depending on the "ghc" package (packages
416 -- depending on doctest is a common example) can
417 -- depending on doctest is a common example) can
417 -- depend on streamly.
418 -- depend on streamly.
419+ ghc-prim >= 0.5.3 && < 0.10
420+ , fusion-plugin-types >= 0.1 && < 0.2
418− base >= 4.12 && < 4.18
421+ , base >= 4.12 && < 4.18
419 , exceptions >= 0.8.0 && < 0.11
422 , exceptions >= 0.8.0 && < 0.11
420− , ghc-prim >= 0.5.3 && < 0.10
421 , transformers >= 0.5.5 && < 0.7
423 , transformers >= 0.5.5 && < 0.7
422
424
423 -- streamly-unicode-core
425 -- streamly-unicode-core
@@ -426,9 +428,6 @@ library
426 -- streamly-filesystem-core
428 -- streamly-filesystem-core
427 , directory >= 1.3.3 && < 1.4
429 , directory >= 1.3.3 && < 1.4
428
430
429− -- fusion-plugin
430− , fusion-plugin-types >= 0.1 && < 0.2
431−
432 -- XXX to be removed
431 -- XXX to be removed
433 , containers >= 0.6.0 && < 0.7
432 , containers >= 0.6.0 && < 0.7
434 , heaps >= 0.3 && < 0.5
433 , heaps >= 0.3 && < 0.5