@@ -271,6 +271,7 @@ module Streamly.Internal.Prelude
271 , intercalateSuffix
271 , intercalateSuffix
272 , interpose
272 , interpose
273 , interposeSuffix
273 , interposeSuffix
275 -- -- ** Breaking
276 -- -- ** Breaking
@@ -2614,6 +2615,72 @@ interposeSuffix :: (IsStream t, Monad m)
2614interposeSuffix x unf str =
2615interposeSuffix x unf str =
2615 D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
2616 D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
2618+------------------------------------------------------------------------------
2620+------------------------------------------------------------------------------
2622+-- | Traverse a forest with recursive tree structures whose non-leaf nodes are
2623+-- of type @a@ and leaf nodes are of type @b@, flattening all the trees into
2624+-- streams and combining the streams into a single stream consisting of both
2625+-- leaf and non-leaf nodes.
2627+-- 'concatMapTreeWith' is a generalization of 'concatMap', using a recursive
2628+-- feedback loop to append the non-leaf nodes back to the input stream enabling
2629+-- recursive traversal. 'concatMap' flattens a single level nesting whereas
2630+-- 'concatMapTreeWith' flattens a recursively nested structure.
2632+-- Traversing a directory tree recursively is a canonical use case of
2633+-- 'concatMapTreeWith'.
2637+{-# INLINE concatMapTreeWith #-}
2640+ => (forall c. t m c -> t m c -> t m c)
2641+ -> (a -> t m (Either a b))
2642+ -> t m (Either a b)
2643+ -> t m (Either a b)
2644+concatMapTreeWith combine f xs = concatMapWith combine go xs
2646+ go (Left tree) = Left tree `K.cons` concatMapWith combine go (f tree)
2647+ go (Right leaf) = yield $ Right leaf
2650+-- | Like concatMapTreeWith but produces only stream of leaf elements.
2652+{-# INLINE concatMapLeavesWith #-}
2653+concatMapLeavesWith :: (IsStream t, MonadAsync m)
2654+ => _ -> (a -> t m (Either a b)) -> t m (Either a b) -> t m b
2655+concatMapLeavesWith combine f xs = undefined
2659+{-# INLINE concatUnfoldTree #-}
2660+concatUnfoldTree :: (IsStream t, MonadAsync m)
2661+ => Unfold m a (Either a b) -> t m (Either a b) -> t m (Either a b)
2662+concatUnfoldTree unf xs = undefined
2664+------------------------------------------------------------------------------
2666+------------------------------------------------------------------------------
2668+-- Flatten a stream with a feedback loop back into the input. For example, if
2669+-- the output stream may generate an exception the exceptions can be fed back
2670+-- to the input to take any corrective action. For example, we may retry the
2671+-- action again or do nothing or log the errors. For the retry case we need a
2674+-- We can perhaps even implement the SVar using this. The stream we are mapping
2675+-- on is the work queue. When evaluated it results in either a leaf element to
2676+-- yield or a tail stream to queue back to the work queue.
2678+{-# INLINE concatMapLoopWith #-}
2679+concatMapLoopWith :: (IsStream t, MonadAsync m)
2680+ => _ -> (a -> t m (Either b c)) -> (b -> t m a) -> t m a -> t m c
2681+concatMapLoopWith combine f xs = undefined
2617------------------------------------------------------------------------------
2684------------------------------------------------------------------------------
2618-- Grouping/Splitting
2685-- Grouping/Splitting
2619------------------------------------------------------------------------------
2686------------------------------------------------------------------------------