Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you want to combine two <code>IO</code>-generated streams, then Gabriel's comment is the solution.</p> <p>Otherwise, you can't wait for both streams, which one produces a value first. Conduits are single-threaded and deterministic - it processes only one pipe at a time. But you could create a function that interleaves two streams, letting them decide when to switch:</p> <pre><code>{-# OPTIONS_GHC -fwarn-incomplete-patterns #-} import Control.Monad (liftM) import Data.Conduit.Internal ( Pipe (..), Source, Sink, injectLeftovers, ConduitM (..), mapOutput, mapOutputMaybe ) -- | Alternate two given sources, running one until it yields `Nothing`, -- then switching to the other one. merge :: Monad m =&gt; Source m (Maybe a) -&gt; Source m (Maybe b) -&gt; Source m (Either a b) merge (ConduitM l) (ConduitM r) = ConduitM $ goL l r where goL :: Monad m =&gt; Pipe () () (Maybe a) () m () -&gt; Pipe () () (Maybe b) () m () -&gt; Pipe () () (Either a b) () m () goL (Leftover l ()) r = goL l r goL (NeedInput _ c) r = goL (c ()) r goL (PipeM mx) r = PipeM $ liftM (`goL` r) mx goL (Done _) r = mapOutputMaybe (liftM Right) r goL (HaveOutput c f (Just o)) r = HaveOutput (goL c r) f (Left o) goL (HaveOutput c f Nothing) r = goR c r -- This is just a mirror copy of goL. We should combine them together to -- avoid code repetition. goR :: Monad m =&gt; Pipe () () (Maybe a) () m () -&gt; Pipe () () (Maybe b) () m () -&gt; Pipe () () (Either a b) () m () goR l (Leftover r ()) = goR l r goR l (NeedInput _ c) = goR l (c ()) goR l (PipeM mx) = PipeM $ liftM (goR l) mx goR l (Done _) = mapOutputMaybe (liftM Left) l goR l (HaveOutput c f (Just o)) = HaveOutput (goR l c) f (Right o) goR l (HaveOutput c f Nothing) = goL l c </code></pre> <p>It processes one source until it returns <code>Nothing</code>, then switches to another, etc. If one source finishes, the other one is processed to the end.</p> <p>As an example, we can combine and interleave two lists:</p> <pre><code>import Control.Monad.Trans import Data.Conduit (($$), awaitForever) import Data.Conduit.List (sourceList) main = (merge (sourceList $ concatMap (\x -&gt; [Just x, Just x, Nothing]) [ 1..10]) (sourceList $ concatMap (\x -&gt; [Just x, Nothing]) [101..110]) ) $$ awaitForever (\x -&gt; lift $ print x) </code></pre> <hr> <p>If you need multiple sources, <code>merge</code> could be adapted to something like</p> <pre><code>mergeList :: Monad m =&gt; [Source m (Maybe a)] -&gt; Source m a </code></pre> <p>which would cycle through the given list of sources until all of them are finished.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload