@@ -271,7 +271,10 @@ module Streamly.Internal.Prelude
271271 , intercalateSuffix
272272 , interpose
273273 , interposeSuffix
274+ , concatMapIterateWith
274275 , concatMapTreeWith
276+ , concatMapLoopWith
277+ , concatMapTreeYieldLeavesWith
275278
276279 -- -- ** Breaking
277280
@@ -2581,6 +2584,23 @@ interposeSuffix x unf str =
25812584-- Flattening Trees
25822585------------------------------------------------------------------------------
25832586
2587+-- | Like 'iterateM' but using a stream generator function.
2588+--
2589+-- /Internal/
2590+--
2591+{-# INLINE concatMapIterateWith #-}
2592+concatMapIterateWith
2593+ :: IsStream t
2594+ => (forall c. t m c -> t m c -> t m c)
2595+ -> (a -> t m a)
2596+ -> t m a
2597+ -> t m a
2598+concatMapIterateWith combine f xs = concatMapWith combine go xs
2599+ where
2600+ go x = yield x `combine` concatMapWith combine go (f x)
2601+
2602+-- concatMapIterateLeftsWith
2603+--
25842604-- | Traverse a forest with recursive tree structures whose non-leaf nodes are
25852605-- of type @a@ and leaf nodes are of type @b@, flattening all the trees into
25862606-- streams and combining the streams into a single stream consisting of both
@@ -2594,6 +2614,13 @@ interposeSuffix x unf str =
25942614-- Traversing a directory tree recursively is a canonical use case of
25952615-- 'concatMapTreeWith'.
25962616--
2617+-- @
2618+-- concatMapTreeWith combine f xs = concatMapIterateWith combine g xs
2619+-- where
2620+-- g (Left tree) = f tree
2621+-- g (Right leaf) = nil
2622+-- @
2623+--
25972624-- /Internal/
25982625--
25992626{-# INLINE concatMapTreeWith #-}
@@ -2601,7 +2628,7 @@ concatMapTreeWith
26012628 :: IsStream t
26022629 => (forall c. t m c -> t m c -> t m c)
26032630 -> (a -> t m (Either a b))
2604− -> t m (Either a b)
2631+ -> t m (Either a b) -- Should be t m a?
26052632 -> t m (Either a b)
26062633concatMapTreeWith combine f xs = concatMapWith combine go xs
26072634 where
@@ -2610,11 +2637,15 @@ concatMapTreeWith combine f xs = concatMapWith combine go xs
26102637
26112638{-
26122639-- | Like concatMapTreeWith but produces only stream of leaf elements.
2640+-- On an either stream, iterate lefts but yield only rights.
26132641--
2614−{-# INLINE concatMapLeavesWith #-}
2615−concatMapLeavesWith :: (IsStream t, MonadAsync m)
2642+-- concatMapEitherYieldRightsWith combine f xs =
2643+-- catRights $ concatMapTreeWith combine f xs
2644+--
2645+{-# INLINE concatMapEitherYieldRightsWith #-}
2646+concatMapEitherYieldRightsWith :: (IsStream t, MonadAsync m)
26162647 => _ -> (a -> t m (Either a b)) -> t m (Either a b) -> t m b
2617−concatMapLeavesWith combine f xs = undefined
2648+concatMapEitherYieldRightsWith combine f xs = undefined
26182649-}
26192650
26202651{-
@@ -2622,6 +2653,7 @@ concatMapLeavesWith combine f xs = undefined
26222653concatUnfoldTree :: (IsStream t, MonadAsync m)
26232654 => Unfold m a (Either a b) -> t m (Either a b) -> t m (Either a b)
26242655concatUnfoldTree unf xs = undefined
2656+-}
26252657
26262658------------------------------------------------------------------------------
26272659-- Feedback loop
@@ -2637,11 +2669,36 @@ concatUnfoldTree unf xs = undefined
26372669-- on is the work queue. When evaluated it results in either a leaf element to
26382670-- yield or a tail stream to queue back to the work queue.
26392671--
2672+-- | Feedback a component of the output back to the input stream.
2673+--
2674+-- /Internal/
2675+--
26402676{-# INLINE concatMapLoopWith #-}
2641−concatMapLoopWith :: (IsStream t, MonadAsync m)
2642− => _ -> (a -> t m (Either b c)) -> (b -> t m a) -> t m a -> t m c
2643−concatMapLoopWith combine f xs = undefined
2644−-}
2677+concatMapLoopWith
2678+ :: (IsStream t, MonadAsync m)
2679+ => (forall x. t m x -> t m x -> t m x)
2680+ -> (a -> t m (Either b c))
2681+ -> (b -> t m a) -- feedback function to feed b back into input
2682+ -> t m a
2683+ -> t m c
2684+concatMapLoopWith combine f fb xs =
2685+ concatMapWith combine go $ concatMapWith combine f xs
2686+ where
2687+ go (Left b) = concatMapLoopWith combine f fb $ fb b
2688+ go (Right c) = yield c
2689+
2690+-- Concat a stream of trees, generating only leaves.
2691+--
2692+-- /Internal/
2693+--
2694+{-# INLINE concatMapTreeYieldLeavesWith #-}
2695+concatMapTreeYieldLeavesWith
2696+ :: (IsStream t, MonadAsync m)
2697+ => (forall x. t m x -> t m x -> t m x)
2698+ -> (a -> t m (Either a b))
2699+ -> t m a
2700+ -> t m b
2701+concatMapTreeYieldLeavesWith combine f = concatMapLoopWith combine f yield
26452702
26462703------------------------------------------------------------------------------
26472704-- Grouping/Splitting