6

今日の初めに、実際にデータをコピーするための iteratee と進行状況を書き込むための iteratee を構成する iteratee 用の小さなテスト アプリを作成しました。私は次のような値で終わりました:

-- NOTE: this snippet is with iteratees-0.8.5.0
-- side effect: display progress on stdout
displayProgress :: Iteratee ByteString IO ()

-- side effect: copy the bytestrings of Iteratee to Handle
fileSink :: Handle -> Iteratee ByteString IO ()

writeAndDisplayProgress :: Handle -> Iteratee ByteString IO ()
writeAndDisplayProgress handle = sequence_ [fileSink handle, displayProgress]

列挙子ライブラリを見ると、sequence_またはの類似物は見当たりませんenumWith。私がやりたいのは、2 つの iteratee を構成して、1 つとして機能させることだけです。結果を破棄することもできます (()とにかくそうなるでしょう) または保持することもできますが、気にしません。(&&&) from Control.Arrow は、矢印ではなく iteratees に対してのみ、私が望むものです。

私はこれらの2つのオプションを試しました:

-- NOTE: this snippet is with enumerator-0.4.10
run_ $ enumFile source $$ sequence_ [iterHandle handle, displayProgress]
run_ $ enumFile source $$ sequence_ [displayProgress, iterHandle handle]

最初のものはファイルをコピーしますが、進行状況は表示されません。2番目のものは進行状況を示しますが、ファイルをコピーしません。したがって、列挙子の反復に対する組み込みの sequence_ の効果は、最初の反復を終了するまで実行してから、もう一方を実行することです。これは私が望むものではありません。iteratees を直列ではなく並列に実行したい。明らかな何かが欠けているように感じwcますが、列挙子ライブラリの例を読んでいると、次の興味深いコメントが表示されます。

-- Exactly matching wc's output is too annoying, so this example
-- will just print one line per file, and support counting at most
-- one statistic per run

この発言は、列挙フレームワーク内で iteratee を組み合わせたり構成したりすることは、そのままでは不可能であることを示しているのだろうか。これを行う一般的に受け入れられている正しい方法は何ですか?

編集

これを行う組み込みの方法はないようです。enumSequencemanyToOneなどのコンビネータの追加について Haskell メーリング リストで議論されていますが、これまでのところ、この機能を提供する enumerator パッケージには実際には何もないようです。

4

1 に答える 1

2

Iteratees2 つのシーケンスを並行して消費しようとするのではなく、Enumeratee通過するバイト数を単純にカウントする ID を介してストリームをフィードする方がよいように思えます。

ファイルをコピーし、各チャンクの後にコピーされたバイト数を出力する簡単な例を次に示します。

import System.Environment
import System.IO
import Data.Enumerator
import Data.Enumerator.Binary (enumFile, iterHandle)
import Data.Enumerator.List (mapAccumM)
import qualified Data.ByteString as B

printBytes :: Enumeratee B.ByteString B.ByteString IO ()
printBytes = flip mapAccumM 0 $ \total bytes -> do
    let total' = total + B.length bytes
    print total'
    return (total', bytes)

copyFile s t = withBinaryFile t WriteMode $ \h -> do
    run_ $ (enumFile s $= printBytes) $$ iterHandle h

main = do
    [source, target] <- getArgs
    copyFile source target
于 2011-07-17T20:20:15.520 に答える