on master help sign in
Add unfoldManyEither combinator

This is required by the "streamly-process" package to unfold the stdout and stderr streams together efficiently.

commit064ac664c590e869302587130409c54250ab5724 authorHarendra Kumar <harendra@composewell.com> dateThu 29 Jul 2021, 01:23 (5 years ago) parent1e00573
2 files changed+36−3
src/Streamly/Internal/Data/Stream/IsStream/Expand.hs+2−2 src/Streamly/Internal/Data/Unfold.hs+34−1
src/Streamly/Internal/Data/Stream/IsStream/Expand.hs+2−2
@@ -379,13 +379,13 @@ mergeBy f m1 m2 = fromStreamS $ S.mergeBy f (toStreamS m1) (toStreamS m2)
379379--
380380-- @
381381-- >>> :{
382−-- do
382+-- do
383383-- let proportionately m n = do
384384-- ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]
385385-- return $ \_ _ -> do
386386-- r <- readIORef ref
387387-- writeIORef ref $ Prelude.tail r
388−-- return $ Prelude.head r
388+-- return $ Prelude.head r
389389-- f <- proportionately 2 1
390390-- xs <- Stream.toList $ Stream.mergeByM f (Stream.fromList [1,1,1,1,1,1]) (Stream.fromList [2,2,2])
391391-- print xs
src/Streamly/Internal/Data/Unfold.hs+34−1
@@ -183,6 +183,9 @@ module Streamly.Internal.Data.Unfold
183183 , mapM
184184 , mapMWithInput
185185
186+ -- ** Either Wrapped Input
187+ , either
188+
186189 -- ** Filtering
187190 , takeWhileM
188191 , takeWhile
@@ -254,7 +257,7 @@ import Streamly.Internal.Data.SVar
254257import Streamly.Internal.Data.Unfold.Type
255258import Prelude
256259 hiding (map, mapM, takeWhile, take, filter, const, zipWith
257− , drop, dropWhile)
260+ , drop, dropWhile, either)
258261
259262-- $setup
260263-- >>> import qualified Streamly.Data.Fold as Fold
@@ -424,6 +427,36 @@ mapMWithInput f (Unfold ustep uinject) = Unfold step inject
424427 Skip s -> return $ Skip (inp, s)
425428 Stop -> return Stop
426429
430+
431+-------------------------------------------------------------------------------
432+-- Either
433+-------------------------------------------------------------------------------
434+
435+-- | Make an unfold operate on values wrapped in an @Either a a@ type. 'Right
436+-- a' translates to 'Right b' and 'Left a' translates to 'Left b'.
437+--
438+-- /Internal/
439+{-# INLINE_NORMAL either #-}
440+either :: Monad m => Unfold m a b -> Unfold m (Either a a) (Either b b)
441+either (Unfold step1 inject1) = Unfold step inject
442+
443+ where
444+
445+ inject (Left a) = do
446+ r <- inject1 a
447+ return (r, Left)
448+ inject (Right a) = do
449+ r <- inject1 a
450+ return (r, Right)
451+
452+ {-# INLINE_LATE step #-}
453+ step (st, f) = do
454+ r <- step1 st
455+ return $ case r of
456+ Yield x s -> Yield (f x) (s, f)
457+ Skip s -> Skip (s, f)
458+ Stop -> Stop
459+
427460-------------------------------------------------------------------------------
428461-- Convert streams into unfolds
429462-------------------------------------------------------------------------------