我使用Haskell流处理库pipes来编写命令行工具。每个命令行操作都可以将结果输出到stdout
,并使用stderr
API记录到pipes
。
我需要Consumer
类型为Consumer (Either String String) m r
来打印数据块(Left
到stderr
,Right
到stdout
)单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
由于
答案 0 :(得分:1)
(这是@Michael的答案,但我想在这里写一下,这样我们就可以将问题移出Haskell标签的未答复队列。)
请参阅pipes-extras中的(+++)
。请注意,Consumer
是Pipe
(无处),所以P.toHandle IO.stderr +++ P.stdoutLn :: MonadIO m => Pipe (Either String String) (Either b d) m ()
。
要获得Consumer
,您必须摆脱Lefts
,例如>-> P.concat
或>-> P.drain
。使用Fold
s有更强大,更美观的方法。