Skip to content

Instantly share code, notes, and snippets.

@snoyberg
Created January 31, 2013 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snoyberg/4682609 to your computer and use it in GitHub Desktop.
Save snoyberg/4682609 to your computer and use it in GitHub Desktop.
combine two Sinks
import Data.Conduit
import Data.Conduit.Internal
import Data.Void (Void, absurd)
import qualified Data.Conduit.List as CL
import Control.Monad (zipWithM_)
import Control.Monad.Trans.Class (lift)
combine :: Monad m
=> Sink i1 m r1
-> Sink i2 m r2
-> Sink (Either i1 i2) m (r1, r2)
combine s1' s2' =
go (injectLeftovers s1') (injectLeftovers s2')
where
go :: Monad m
=> Pipe Void i1 Void () m r1
-> Pipe Void i2 Void () m r2
-> Pipe l (Either i1 i2) Void () m (r1, r2)
go (HaveOutput _ _ o) _ = absurd o
go _ (HaveOutput _ _ o) = absurd o
go (Leftover _ l) _ = absurd l
go _ (Leftover _ l) = absurd l
go (Done r1) s2 = do
r2 <- lift $ runPipe $ return () >+> s2
return (r1, r2)
go s1 (Done r2) = do
r1 <- lift $ runPipe $ return () >+> s1
return (r1, r2)
go (PipeM m1) s2 = do
s1 <- lift m1
go s1 s2
go s1 (PipeM m2) = do
s2 <- lift m2
go s1 s2
go (NeedInput p1 c1) (NeedInput p2 c2) =
NeedInput p c
where
p (Left i1) = go (p1 i1) (NeedInput p2 c2)
p (Right i2) = go (NeedInput p1 c1) (p2 i2)
c () = go (c1 ()) (c2 ())
source :: Monad m => Source m (Either Char Int)
source =
zipWithM_ go "hello world" [1..]
where
go x y = yield (Left x) >> yield (Right y)
sink :: Monad m => Sink (Either Char Int) m (String, Int)
sink = combine CL.consume (CL.fold (+) 0)
main :: IO ()
main = (source $$ sink) >>= print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment