I use Haskell stream processing library pipes to write a command line tool. Each command line actions may output result to stdout
and logs to stderr
with pipes
API.
I need Consumer
which has type as Consumer (Either String String) m r
to print chunk of data (Left
to stderr
, Right
to stdout
) with single Consumer
.
This function consumeEither
doesn't have flexibility so I want to improve it.
consumeEither :: (MonadIO m) => Consumer (Either String String) m ()
consumeEither = do
eitherS <- await
case eitherS of
(Left l) -> for (yield l) (liftIO . (IO.hPutStrLn IO.stderr))
(Right r) -> for (yiled r) (liftIO . putStrLn)
Furthermore it would be useful to provide a function which takes two Consumer
s and merge them into one Consumer
.
Does anybody know good example or implementation of the following interface?
merge :: (Monad m) => Consumer a m r -> Consumer b m r -> Consumer (Either a b) m r
stderr
stdout
import Pipes
import qualified Pipes.Prelude as P
import qualified System.IO as IO
stdoutOrErr :: Consumer (Either String String) IO ()
stdoutOrErr = merge (P.toHandle IO.stderr) P.stdoutLn
Thanks
(This is @Michael's answer, but I'd like to write it up here so we can move the question out of the unanswered queue for the Haskell tag.)
See (+++)
in pipes-extras. Keep in mind a Consumer
is a Pipe
(to nowhere), so P.toHandle IO.stderr +++ P.stdoutLn :: MonadIO m => Pipe (Either String String) (Either b d) m ()
.
To get a Consumer
, you would have to get rid of the Lefts
e.g with >-> P.concat
or >-> P.drain
. There are more robust and handsome ways of doing this with Fold
s.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With