3

私はこのコードを持っています:

import Pipes
import Pipes.Safe
import qualified Pipes.Prelude as P
import qualified Pipes.Safe.Prelude as P
import System.IO

import Data.Text as T
import Data.Text.IO as TIO
import qualified Pipes.Prelude.Text as T

someFunc :: IO ()
someFunc = runSafeT $
  P.withFile file1 ReadMode $ \file1Handle -> do
    file2 <- liftIO $ TIO.hGetLine file1Handle
    runEffect $
      for (P.zip (T.fromHandleLn file1Handle)
                 (T.readFileLn $ T.unpack file2))
          (\(l1,l2) -> do yield l2
                          yield l1)
      >-> T.stdoutLn

しかし、それは非常にハックに思えます.最初のファイルの最初の行で読んだものから、パイプ内から2番目のファイルを開くことができるようにしたいと思います. 何か案が?

4

1 に答える 1

2

Data.Text.IO混同せずにこれを行う方法はいくつかあると思いますPipeszipあなたが言うように、それは基本的にです。最初のファイルの最初の行を見つける自然な方法は、これを使用することnextです。この場合、残りの行とペアになった最初の行が得られます。

someFunc_ = runSafeT $ runEffect $ do 
  e <- next (T.readFileLn file1)
  case e of
    Left r              -> return r
    Right (file2, rest) -> do 
      let other = T.readFileLn (T.unpack file2)
          amalgam = for (P.zip rest other) $ \(l1,l2) -> do
            yield l2 
            yield l1
      runEffect $ amalgam >-> T.stdoutLn

「パイプライン内」でより多くのことをしようとしたアプローチは、価値があるよりも複雑になると思います。特に、file1 が空になった場合に対処する必要があります。nextは基本的にパイプでのパターン マッチに使用するものProducerであるため、基本的なパイプ操作です。

したがって、部分的には、基本的にはこのような通常のテキスト プログラムと同じです。

 someFunc = do
    ls <- fmap T.lines TIO.readFile file1 
    case ls of
      []         -> return ()
      file2:rest -> do 
        ls' <- fmap T.lines (TIO.readFile file1) 
        forM_ (zip ls ls') $ \(t1,t2) -> do
             TIO.putStrLn t1
             TIO.putStrLn t2

ただし、適切にストリーミングされます。

于 2016-08-25T20:56:06.463 に答える