@@ -33,6 +33,8 @@ module Streamly.Internal.Data.Stream.StreamK.Type
3333 -- * Elimination
3434 , foldStream
3535 , foldStreamShared
36+ , foldl'
37+ , foldlx'
3638
3739 -- * foldr/build
3840 , foldrM
@@ -755,6 +757,48 @@ foldrMKWith f step acc g = go g
755757 foldrM step acc (sharedM g) = foldrMKWith foldStreamShared step acc g
756758 #-}
757759
760+------------------------------------------------------------------------------
761+-- Left fold
762+------------------------------------------------------------------------------
763+
764+-- | Strict left fold with an extraction function. Like the standard strict
765+-- left fold, but applies a user supplied extraction function (the third
766+-- argument) to the folded value at the end. This is designed to work with the
767+-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
768+--
769+-- Note that the accumulator is always evaluated including the initial value.
770+{-# INLINE foldlx' #-}
771+foldlx' :: forall t m a b x. (IsStream t, Monad m)
772+ => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
773+foldlx' step begin done m = get $ go m begin
774+ where
775+ {-# NOINLINE get #-}
776+ get :: t m x -> m b
777+ get m1 =
778+ -- XXX we are not strictly evaluating the accumulator here. Is this
779+ -- okay?
780+ let single = return . done
781+ -- XXX this is foldSingleton. why foldStreamShared?
782+ in foldStreamShared undefined undefined single undefined m1
783+
784+ -- Note, this can be implemented by making a recursive call to "go",
785+ -- however that is more expensive because of unnecessary recursion
786+ -- that cannot be tail call optimized. Unfolding recursion explicitly via
787+ -- continuations is much more efficient.
788+ go :: t m a -> x -> t m x
789+ go m1 !acc = mkStream $ \_ yld sng _ ->
790+ let stop = sng acc
791+ single a = sng $ step acc a
792+ -- XXX this is foldNonEmptyStream
793+ yieldk a r = foldStream defState yld sng undefined $
794+ go r (step acc a)
795+ in foldStream defState yieldk single stop m1
796+
797+-- | Strict left associative fold.
798+{-# INLINE foldl' #-}
799+foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
800+foldl' step begin = foldlx' step begin id
801+
758802------------------------------------------------------------------------------
759803-- Semigroup
760804------------------------------------------------------------------------------