@@ -155,11 +155,17 @@ module Streamly.Streams.StreamD
155155
156156 , prescanl'
157157 , prescanlM'
158+
158159 , postscanl
159160 , postscanlM
160161 , postscanl'
161162 , postscanlM'
162163
164+ , postscanlx'
165+ , postscanlMx'
166+ , scanlMx'
167+ , scanlx'
168+
163169 -- * Filtering
164170 , filter
165171 , filterM
@@ -229,6 +235,23 @@ import qualified Streamly.Streams.StreamK as K
229235nil :: Monad m => Stream m a
230236nil = Stream (\_ _ -> return Stop) ()
231237
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
241+ where
242+ {-# INLINE_LATE step1 #-}
243+ step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
244+ step1 gst (Just st) = do
245+ r <- step gst st
246+ return $
247+ case r of
248+ Yield a s -> Yield a (Just s)
249+ Skip s -> Skip (Just s)
250+ Stop -> Stop
251+
252+-- XXX implement in terms of consM?
253+-- cons x = consM (return x)
254+--
232255-- | Can fuse but has O(n^2) complexity.
233256{-# INLINE_NORMAL cons #-}
234257cons :: Monad m => a -> Stream m a -> Stream m a
@@ -983,6 +1006,10 @@ fromStreamD = K.fromStream . toStreamK
9831006-- Transformation by Folding (Scans)
9841007------------------------------------------------------------------------------
9851008
1009+------------------------------------------------------------------------------
1010+-- Prescans
1011+------------------------------------------------------------------------------
1012+
9861013-- XXX Is a prescan useful, discarding the last step does not sound useful? I
9871014-- am not sure about the utility of this function, so this is implemented but
9881015-- 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)
10111038prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
10121039prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
10131040
1041+------------------------------------------------------------------------------
1042+-- Monolithic postscans (postscan followed by a map)
1043+------------------------------------------------------------------------------
1044+
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.
1049+--
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)
1055+ where
1056+ {-# INLINE_LATE step' #-}
1057+ step' gst (st, acc) = do
1058+ r <- step (adaptState gst) st
1059+ case r of
1060+ Yield x s -> do
1061+ old <- acc
1062+ y <- fstep old x
1063+ v <- done y
1064+ v `seq` y `seq` return (Yield v (s, return y))
1065+ Skip s -> return $ Skip (s, acc)
1066+ Stop -> return Stop
1067+
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
1073+
1074+-- XXX do we need consM strict to evaluate the begin value?
1075+{-# INLINE scanlMx' #-}
1076+scanlMx' :: Monad m
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
1080+
1081+{-# INLINE scanlx' #-}
1082+scanlx' :: Monad m
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
1086+
1087+------------------------------------------------------------------------------
1088+-- postscans
1089+------------------------------------------------------------------------------
1090+
10141091-- XXX if we make the initial value of the accumulator monadic then should we
10151092-- execute it even if the stream is empty? In that case we would have generated
10161093-- the effect but discarded the value, but that is what a fold does when the