今天早些时候,我为 iteratee 编写了一个小型测试应用程序,该应用程序组成了一个用于写入进度的 iteratee 和一个用于实际复制数据的 iteratee。我最终得到了这样的值(value)观:
-- 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
我想知道这句话是否表明在枚举框架内组合或组合迭代器是不可能开箱即用的。普遍接受的正确方法是什么?
编辑:
似乎没有内置的方法可以做到这一点。 Haskell 邮件列表上有关于添加组合器的讨论,如 enumSequence和 manyToOne但到目前为止,枚举器包中实际上似乎没有任何东西可以提供此功能。
最佳答案
在我看来,与其尝试让两个 Iteratee
并行使用该序列,不如通过一个简单计数的身份 Enumeratee
来提供流传递它的字节。
这是一个简单的示例,它复制文件并打印每个 block 后复制的字节数。
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
关于Haskell 枚举器 : analog to iteratees `enumWith` operator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6688898/