2011-07-14 32 views
6

今天早些時候,我爲迭代編寫了一個小測試應用程序,它構成一個迭代器,用於爲實際複製數據編寫迭代器的進度。我結束了這樣的價值觀:在探究枚舉庫Haskell枚舉器:類似於迭代`enumWith`運算符?

-- 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模擬。我想要做的就是組成兩個迭代,所以它們是一樣的。我可以放棄結果(反正它會是())或保留它,我不在乎。 (& & &)從Control.Arrow是我想要的,只爲迭代而不是箭頭。

我想這兩個選項:

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

第一個文件副本,但不顯示進度;第二個顯示進度,但不復制文件,所以顯然內置sequence_對枚舉器迭代的影響是運行第一個迭代器直到它終止,然後運行另一個,這不是我想要的。我想要並行運行迭代,而不是串行運行。我覺得我失去了一些東西很明顯,但在閱讀了枚舉庫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 

我不知道這句話表明,合併或組成枚舉框架內ISN iteratees開箱即可。什麼是普遍接受的正確方法?

編輯

這好像沒有內置的方式做到這一點。 Haskell郵件列表討論瞭如何添加組合器(如enumSequencemanyToOne),但到目前爲止,在提供此功能的枚舉器包中似乎沒有任何實際內容。

+0

我沒有花足夠長的時間看文檔,以制定和測試真正的答案,但它看起來像表面上'Enumerator's和'Enumeratee's是你想要的方式組合的。 (PS我猜你是在談論Hackage上的「enumerator」包,你應該先說一下,因爲現在有六種不同的iteratees實現。=) –

+0

你也沒有花錢足夠的時間閱讀我的問題。 –

+0

這有點粗魯,考慮到我剛剛花了一點時間幫助你解決你的問題。也許你可以指出你認爲我錯過了的部分,而不是諷刺。 –

回答

2

在我看來,似乎並非試圖讓兩個Iteratees並行地使用該序列,最好是通過簡單地計數傳遞它的字節的身份Enumeratee來提供該流。

下面是一個簡單的示例,它複製文件並打印每個塊後複製的字節數。

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