有没有办法用Haskell的管道模拟三通?

use*_*931 3 haskell conduit

我试图从Haskell程序中生成一个进程,我想将其标准错误流打印到屏幕,同时也将相同的流写入文件,就像tee命令实现的那样.

我可以打印标准错误流:

import Data.Conduit ((.|), runConduit)
import qualified Data.Conduit.List as CL
import Data.Conduit.Process

main :: IO ()
main = do
  (ClosedStream, ClosedStream, err, sph) <- streamingProcess (shell myCommand)

  runConduit $ err .| CL.mapM_ print
Run Code Online (Sandbox Code Playgroud)

我可以将流指向文件:

import System.IO (withFile, IOMode (..))
import Data.Conduit.Process

main :: IO ()
main = do
  let logFile = "myCommand.log"
  withFile logFile WriteMode $ \h -> do
    (ClosedStream, ClosedStream, UseProvidedHandle, sph) <-
      streamingProcess (shell myCommand) {std_err = UseHandle h}
Run Code Online (Sandbox Code Playgroud)

我怎样才能同时做到这两件事?

Mic*_*man 6

一种方法是使用该conduitFile功能:

#!/usr/bin/env stack
-- stack --resolver lts-10.3 script
import Conduit
import Data.Conduit.Process
import Data.Conduit.Binary (conduitFile)

main :: IO ()
main = do
(ClosedStream, out, ClosedStream, ph) <-
    streamingProcess (shell "cat /etc/passwd")

runConduitRes $ out .| conduitFile "myCommand.log" .| printC
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用ZipSink两种不同的方式同时使用流:

#!/usr/bin/env stack
-- stack --resolver lts-10.3 script
import Conduit
import Data.Conduit.Process

main :: IO ()
main = do
(ClosedStream, out, ClosedStream, ph) <-
    streamingProcess (shell "cat /etc/passwd")

runConduitRes $ out .| getZipSink (
    ZipSink (sinkFile "myCommand.log") *>
    ZipSink printC)
Run Code Online (Sandbox Code Playgroud)