如何在Haskell Pipes中将两个Consumer合并为一个?

ily*_*tre 11 haskell pipe

我使用Haskell流处理库管道来编写命令行工具.每个命令行操作都可以将结果输出stdout到API 并stderr使用pipesAPI 登录.

我需要Consumer哪种类型的Consumer (Either String String) m r打印数据块(Leftto stderr,Rightto stdout)与single Consumer.

我写的代码(应该改进)

这个功能consumeEither没有灵活性,所以我想改进它.

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)
Run Code Online (Sandbox Code Playgroud)

此外,提供一个需要两个Consumer并将它们合并为一个的函数将是有用的Consumer.

有没有人知道以下界面的好例子或实现?

merge :: (Monad m) => Consumer a m r -> Consumer b m r -> Consumer (Either a b) m r
Run Code Online (Sandbox Code Playgroud)
  • 第一个论点为 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
Run Code Online (Sandbox Code Playgroud)

谢谢

hao*_*hao 1

(这是 @Michael 的答案,但我想把它写在这里,以便我们可以将问题从 Haskell 标签的未答复队列中移出。)

请参阅(+++)Pipes -extras。请记住 aConsumer是 a Pipe(无处可去),所以P.toHandle IO.stderr +++ P.stdoutLn :: MonadIO m => Pipe (Either String String) (Either b d) m ().

要得到 a ,您必须用orConsumer去掉eg 。有更强大和更漂亮的方法可以用s 来做到这一点。Lefts>-> P.concat>-> P.drainFold