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

时间:2015-04-29 01:30:59

标签: haskell pipe

我使用Haskell流处理库pipes来编写命令行工具。每个命令行操作都可以将结果输出到stdout,并使用stderr API记录到pipes

我需要Consumer类型为Consumer (Either String String) m r来打印数据块(LeftstderrRightstdout)单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)

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

问题

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

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

由于

1 个答案:

答案 0 :(得分:1)

(这是@Michael的答案,但我想在这里写一下,这样我们就可以将问题移出Haskell标签的未答复队列。)

请参阅pipes-extras中的(+++)。请注意,ConsumerPipe(无处),所以P.toHandle IO.stderr +++ P.stdoutLn :: MonadIO m => Pipe (Either String String) (Either b d) m ()

要获得Consumer,您必须摆脱Lefts,例如>-> P.concat>-> P.drain。使用Fold s有更强大,更美观的方法。