何时在流bytestring上致电RunResourcet



我是Haskell初学者,仍在学习Monad Transformers。

我正在尝试使用流式bytestring库来读取二进制文件,处理字节块,并在处理每个块时打印结果。我相信这是一个流行的streaming库,可替代懒惰的字节。作者看来复制了懒惰的Bytestring文档,并添加了一些任意示例。

示例提及 runResourceT,而无需讨论它是什么或如何使用它。看来应在执行动作的任何流式bytestring函数上使用runResourceT。很好,但是,如果我正在阅读一个无限的流来处理块并打印它们怎么办?每次我要处理块时,我都应该致电runresourcet吗?

我的代码就是这样:

import qualified Data.ByteString.Streaming as BSS
import System.TimeIt
main = timeIt $ processByteChunks $ BSS.drop 100 $ BSS.readFile "filename"

我不确定如何组织processByteChunks作为通过二进制文件迭代的递归函数。

如果我只致电runResourceT一次,它将在打印之前读取无限文件,对吗?这似乎很糟糕。

main = timeIt $ runResourceT $ processByteChunks $ BSS.drop 100 $ BSS.readFile "filename"

ResourceT MONAD刚好及时清理资源。在这种情况下,它将确保BSS.readFile打开的文件句柄在消耗流时关闭。(除非流确实是无限的,否则我想不会。(

在您的应用程序中,您只想调用一次,因为在阅读所有块之前,您不希望文件关闭。不用担心 - 它与输出的时间或类似的时间无关。

这是一个应该使用的递归processByteChunks的示例。它会懒惰地读取并产生输出,因为块懒洋洋地阅读:

import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import qualified Data.ByteString.Streaming as BSS
import qualified Data.ByteString as BS
import System.TimeIt
main :: IO ()
main = timeIt $ runResourceT $
  processByteChunks $ BSS.drop 100 $ BSS.readFile "filename"
processByteChunks :: MonadIO m => BSS.ByteString m () -> m ()
processByteChunks = go 0 0
  where go len nulls stream = do
          m <- BSS.unconsChunk stream
          case m of
            Just (bs, stream') -> do
              let len' = len + BS.length bs
                  nulls' = nulls + BS.length (BS.filter (==0) bs)
              liftIO $ print $ "cumulative length=" ++ show len'
                                      ++ ", nulls=" ++ show nulls'
              go len' nulls' stream'
            Nothing -> return ()

最新更新