@@ -154,8 +154,12 @@ foldrM step acc m = go (toStream m)
154 yield a (Just x) = step a (go x)
154 yield a (Just x) = step a (go x)
155 in (runStream m1) Nothing stop yield
155 in (runStream m1) Nothing stop yield
157−-- | Strict left fold. This is typed to work with the foldl package. To use
157+-- XXX This more straightforward implementation of fold is almost twice as
158−-- directly pass 'id' as the third argument.
158+-- costly as the implementation we are using! Need to figure out what's wrong
159+-- with it. Is it GHC that is not able to optimize this somehow? Or is it
160+-- something else? In fact scan is more optimal than this. The fold we are
161+-- using is actually a @scan@ where we discard the intermediate values!
159foldl :: (Streaming t, Monad m)
163foldl :: (Streaming t, Monad m)
160 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
164 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
161foldl step begin done m = go begin (toStream m)
165foldl step begin done m = go begin (toStream m)
@@ -165,7 +169,38 @@ foldl step begin done m = go begin (toStream m)
165 yield a Nothing = return (done (step acc a))
169 yield a Nothing = return (done (step acc a))
166 yield a (Just x) = go (step acc a) x
170 yield a (Just x) = go (step acc a) x
167 in (runStream m1) Nothing stop yield
171 in (runStream m1) Nothing stop yield
174+-- XXX We implement fold like a scan but just drop the intermediate steps and
175+-- extract the last step as the only element from the stream. We also use a
176+-- NOINLINE on the extraction function but INLINE the fold function. This seems
177+-- to work well with the GHC simplifier and we get almost 50% reduction in
178+-- cost! Need to figure what's going on with GHC simplifier, why is the simpler
179+-- code above is not optimal.
181+-- | Strict left fold. This is typed to work with the foldl package. To use
182+-- it normally just pass 'id' as the third argument.
184+foldl :: (Streaming t, Monad m)
185+ => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
186+foldl step begin done m = get $ go (toStream m) begin
188+ {-# NOINLINE get #-}
190+ let yield a Nothing = return $ done a
191+ yield _ _ = undefined
192+ in (runStream m1) Nothing undefined yield
194+ go m1 !acc = Stream $ \_ stp yld ->
196+ stop = yld acc Nothing
197+ yield a Nothing = yld (step acc a) Nothing
200+ in (runStream (go x s)) Nothing stp yld
201+ in (runStream m1) Nothing stop yield
203+-- XXX Need to measure perf and optimize like foldl if needed.
169-- | Strict left fold, with monadic step function. This is typed to work
204-- | Strict left fold, with monadic step function. This is typed to work
170-- with the foldl package. To use directly pass 'id' as the third argument.
205-- with the foldl package. To use directly pass 'id' as the third argument.
171foldlM :: (Streaming t, Monad m)
206foldlM :: (Streaming t, Monad m)