Haskell Lazy ByteString + функция прогресса чтения / записи

Я изучаю Haskell Lazy IO.

Я ищу элегантный способ скопировать большой файл (8 ГБ) во время печати хода копирования на консоль.

Рассмотрим следующую простую программу, которая копирует файл

module Main where

import System
import qualified Data.ByteString.Lazy as B

main = do [from, to] <- getArgs
          body <- B.readFile from
          B.writeFile to body

Представьте, что есть функция обратного вызова, которую вы хотите использовать для отчетности:

onReadBytes :: Integer -> IO ()
onReadBytes count = putStrLn $ "Bytes read: " ++ (show count)

ВОПРОС: как встроить функцию onReadBytes в Lazy ByteString, чтобы она вызывалась при успешном чтении? Или, если этот дизайн не очень хорош, то как это сделать в Haskell?

ПРИМЕЧАНИЕ: частота обратного вызова не важна, его можно вызывать каждые 1024 байта или каждый 1 Мбайт - не важно

ОТВЕТ: Большое спасибо camccann за ответ. Я предлагаю прочитать его целиком.

Ниже представлена ​​моя версия кода, основанная на коде Camccann, вы можете найти его полезным.

module Main where

import System
import System.IO
import qualified Data.ByteString.Lazy as B

main = do [from, to] <- getArgs
          withFile from ReadMode $ \fromH ->
            withFile to WriteMode $ \toH ->
              copyH fromH toH $ \x -> putStrLn $ "Bytes copied: " ++ show x

copyH :: Handle -> Handle -> (Integer -> IO()) -> IO ()
copyH fromH toH onProgress =
    copy (B.hGet fromH (256 * 1024)) (write toH) B.null onProgress
    where write o x  = do B.hPut o x
                          return . fromIntegral $ B.length x

copy :: (Monad m) => m a -> (a -> m Integer) -> (a -> Bool) -> (Integer -> m()) -> m()
copy = copy_ 0

copy_ :: (Monad m) => Integer -> m a -> (a -> m Integer) -> (a -> Bool) -> (Integer -> m()) -> m()
copy_ count inp outp done onProgress = do x <- inp
                                          unless (done x) $
                                            do n <- outp x
                                               onProgress (n + count)
                                               copy_ (n + count) inp outp done onProgress
20
задан oshyshko 14 July 2011 в 18:11
поделиться