on master help sign in
Add hoist and generally for streams
8351c93Harendra Kumar
benchmark/Linear.hs+8
@@ -48,6 +48,13 @@ benchIOSink
48 => String -> (t IO Int -> IO b) -> Benchmark
48 => String -> (t IO Int -> IO b) -> Benchmark
49benchIOSink name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
49benchIOSink name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
50
50
51+{-# INLINE benchHoistSink #-}
52+benchHoistSink
53+ :: (IsStream t, NFData b)
54+ => String -> (t Identity Int -> IO b) -> Benchmark
55+benchHoistSink name f =
56+ bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.sourceUnfoldr
57+
51-- XXX once we convert all the functions to use this we can rename this to
58-- XXX once we convert all the functions to use this we can rename this to
52-- benchIOSink
59-- benchIOSink
53{-# INLINE benchIOSink1 #-}
60{-# INLINE benchIOSink1 #-}
@@ -208,6 +215,7 @@ main =
208 , benchIOSink "or" Ops.or
215 , benchIOSink "or" Ops.or
209
216
210 , benchIOSink "length" Ops.length
217 , benchIOSink "length" Ops.length
218+ , benchHoistSink "length . generally" (Ops.length . IP.generally)
211 , benchIOSink "sum" Ops.sum
219 , benchIOSink "sum" Ops.sum
212 , benchIOSink "product" Ops.product
220 , benchIOSink "product" Ops.product
213
221
src/Streamly/Internal/Data/SVar.hs+1−1
@@ -536,7 +536,7 @@ defState = State
536-- appropriate unStream functions instead.
536-- appropriate unStream functions instead.
537--
537--
538-- | Adapt the stream state from one type to another.
538-- | Adapt the stream state from one type to another.
539−adaptState :: State t m a -> State t m b
539+adaptState :: State t m a -> State t n b
540adaptState st = st
540adaptState st = st
541 { streamVar = Nothing
541 { streamVar = Nothing
542 , _yieldLimit = Nothing
542 , _yieldLimit = Nothing
src/Streamly/Internal/Prelude.hs+11
@@ -133,6 +133,8 @@ module Streamly.Internal.Prelude
133
133
134 -- * Transformation
134 -- * Transformation
135 , transform
135 , transform
136+ , hoist
137+ , generally
136
138
137 -- ** Mapping
139 -- ** Mapping
138 , Serial.map
140 , Serial.map
@@ -1469,6 +1471,15 @@ toPureRev = foldl' (flip K.cons) K.nil
1469transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
1471transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
1470transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
1472transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
1471
1473
1474+{-# INLINE hoist #-}
1475+hoist :: (Monad m, Monad n)
1476+ => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
1477+hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
1478+
1479+{-# INLINE generally #-}
1480+generally :: (IsStream t, Monad m) => t Identity a -> t m a
1481+generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
1482+
1472------------------------------------------------------------------------------
1483------------------------------------------------------------------------------
1473-- Transformation by Folding (Scans)
1484-- Transformation by Folding (Scans)
1474------------------------------------------------------------------------------
1485------------------------------------------------------------------------------
src/Streamly/Streams/StreamD.hs+18−3
@@ -188,6 +188,8 @@ module Streamly.Streams.StreamD
188 , toListRev
188 , toListRev
189 , toStreamK
189 , toStreamK
190 , toStreamD
190 , toStreamD
191+ , hoist
192+ , generally
191
193
192 -- * Transformation
194 -- * Transformation
193 , transform
195 , transform
@@ -290,9 +292,7 @@ import Control.Monad.Catch (MonadCatch)
290import Control.Monad.IO.Class (MonadIO(..))
292import Control.Monad.IO.Class (MonadIO(..))
291import Control.Monad.Trans (MonadTrans(lift))
293import Control.Monad.Trans (MonadTrans(lift))
292import Data.Bits (shiftR, shiftL, (.|.), (.&.))
294import Data.Bits (shiftR, shiftL, (.|.), (.&.))
293−#if __GLASGOW_HASKELL__ >= 801
294−import Data.Functor.Identity (Identity)
295+import Data.Functor.Identity (Identity(..))
295−#endif
296import Data.Maybe (fromJust, isJust)
296import Data.Maybe (fromJust, isJust)
297import Data.Word (Word32)
297import Data.Word (Word32)
298import Foreign.Ptr (Ptr)
298import Foreign.Ptr (Ptr)
@@ -635,6 +635,21 @@ fromListM = Stream step
635toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
635toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
636toStreamD = fromStreamK . K.toStream
636toStreamD = fromStreamK . K.toStream
637
637
638+{-# INLINE_NORMAL hoist #-}
639+hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
640+hoist f (Stream step state) = (Stream step' state)
641+ where
642+ step' gst st = do
643+ r <- f $ step (adaptState gst) st
644+ return $ case r of
645+ Yield x s -> Yield x s
646+ Skip s -> Skip s
647+ Stop -> Stop
648+
649+{-# INLINE_NORMAL generally #-}
650+generally :: Monad m => Stream Identity a -> Stream m a
651+generally = hoist (return . runIdentity)
652+
638------------------------------------------------------------------------------
653------------------------------------------------------------------------------
639-- Elimination by Folds
654-- Elimination by Folds
640------------------------------------------------------------------------------
655------------------------------------------------------------------------------
src/Streamly/Streams/StreamK.hs+14−1
@@ -124,6 +124,7 @@ module Streamly.Streams.StreamK
124 -- ** Conversions
124 -- ** Conversions
125 , toList
125 , toList
126 , toStreamK
126 , toStreamK
127+ , hoist
127
128
128 -- * Transformation
129 -- * Transformation
129 -- ** By folding (scans)
130 -- ** By folding (scans)
@@ -187,7 +188,7 @@ module Streamly.Streams.StreamK
187where
188where
188
189
189import Control.Monad.Trans (MonadTrans(lift))
190import Control.Monad.Trans (MonadTrans(lift))
190−import Control.Monad (void)
191+import Control.Monad (void, join)
191import Control.Monad.Reader.Class (MonadReader(..))
192import Control.Monad.Reader.Class (MonadReader(..))
192import Prelude
193import Prelude
193 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
194 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
@@ -726,6 +727,18 @@ toList = foldr (:) []
726toStreamK :: Stream m a -> Stream m a
727toStreamK :: Stream m a -> Stream m a
727toStreamK = id
728toStreamK = id
728
729
730+-- Based on suggestions by David Feuer and Pranay Sashank
731+{-# INLINE hoist #-}
732+hoist :: (IsStream t, Monad m, Monad n)
733+ => (forall x. m x -> n x) -> t m a -> t n a
734+hoist f str =
735+ mkStream $ \st yld sng stp ->
736+ let single = return . sng
737+ yieldk a s = return $ yld a (hoist f s)
738+ stop = return stp
739+ state = adaptState st
740+ in join . f $ foldStreamShared state yieldk single stop str
741+
729-------------------------------------------------------------------------------
742-------------------------------------------------------------------------------
730-- Transformation by folding (Scans)
743-- Transformation by folding (Scans)
731-------------------------------------------------------------------------------
744-------------------------------------------------------------------------------