@@ -155,11 +155,17 @@ module Streamly.Streams.StreamD
156 , prescanl'
156 , prescanl'
157 , prescanlM'
157 , prescanlM'
158 , postscanl
159 , postscanl
159 , postscanlM
160 , postscanlM
160 , postscanl'
161 , postscanl'
161 , postscanlM'
162 , postscanlM'
163 -- * Filtering
169 -- * Filtering
165 , filterM
171 , filterM
@@ -229,6 +235,23 @@ import qualified Streamly.Streams.StreamK as K
229nil :: Monad m => Stream m a
235nil :: Monad m => Stream m a
230nil = Stream (\_ _ -> return Stop) ()
236nil = Stream (\_ _ -> return Stop) ()
238+{-# INLINE_NORMAL consM #-}
239+consM :: Monad m => m a -> Stream m a -> Stream m a
240+consM m (Stream step state) = Stream step1 Nothing
242+ {-# INLINE_LATE step1 #-}
243+ step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
244+ step1 gst (Just st) = do
248+ Yield a s -> Yield a (Just s)
249+ Skip s -> Skip (Just s)
252+-- XXX implement in terms of consM?
253+-- cons x = consM (return x)
232-- | Can fuse but has O(n^2) complexity.
255-- | Can fuse but has O(n^2) complexity.
233{-# INLINE_NORMAL cons #-}
256{-# INLINE_NORMAL cons #-}
234cons :: Monad m => a -> Stream m a -> Stream m a
257cons :: Monad m => a -> Stream m a -> Stream m a
@@ -983,6 +1006,10 @@ fromStreamD = K.fromStream . toStreamK
983-- Transformation by Folding (Scans)
1006-- Transformation by Folding (Scans)
984------------------------------------------------------------------------------
1007------------------------------------------------------------------------------
1009+------------------------------------------------------------------------------
1011+------------------------------------------------------------------------------
986-- XXX Is a prescan useful, discarding the last step does not sound useful? I
1013-- XXX Is a prescan useful, discarding the last step does not sound useful? I
987-- am not sure about the utility of this function, so this is implemented but
1014-- am not sure about the utility of this function, so this is implemented but
988-- not exposed. We can expose it if someone provides good reasons why this is
1015-- not exposed. We can expose it if someone provides good reasons why this is
@@ -1011,6 +1038,56 @@ prescanlM' f mz (Stream step state) = Stream step' (state, mz)
1011prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1038prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1012prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
1039prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
1041+------------------------------------------------------------------------------
1042+-- Monolithic postscans (postscan followed by a map)
1043+------------------------------------------------------------------------------
1045+-- The performance of a modular postscan followed by a map seems to be
1046+-- equivalent to this monolithic scan followed by map therefore we may not need
1047+-- this implementation. We just have it for performance comparison and in case
1048+-- modular version does not perform well in some situation.
1050+{-# INLINE_NORMAL postscanlMx' #-}
1051+postscanlMx' :: Monad m
1052+ => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1053+postscanlMx' fstep begin done (Stream step state) = do
1054+ Stream step' (state, begin)
1056+ {-# INLINE_LATE step' #-}
1057+ step' gst (st, acc) = do
1058+ r <- step (adaptState gst) st
1064+ v `seq` y `seq` return (Yield v (s, return y))
1065+ Skip s -> return $ Skip (s, acc)
1066+ Stop -> return Stop
1068+{-# INLINE_NORMAL postscanlx' #-}
1069+postscanlx' :: Monad m
1070+ => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1071+postscanlx' fstep begin done s =
1072+ postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1074+-- XXX do we need consM strict to evaluate the begin value?
1075+{-# INLINE scanlMx' #-}
1077+ => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1078+scanlMx' fstep begin done s =
1079+ (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
1081+{-# INLINE scanlx' #-}
1083+ => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1084+scanlx' fstep begin done s =
1085+ scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1087+------------------------------------------------------------------------------
1089+------------------------------------------------------------------------------
1014-- XXX if we make the initial value of the accumulator monadic then should we
1091-- XXX if we make the initial value of the accumulator monadic then should we
1015-- execute it even if the stream is empty? In that case we would have generated
1092-- execute it even if the stream is empty? In that case we would have generated
1016-- the effect but discarded the value, but that is what a fold does when the
1093-- the effect but discarded the value, but that is what a fold does when the