Использование труб для чтения и записи двоичных данных в Haskell

Я пытаюсь читать и писать очень много ints в постоянной памяти. Я выяснил, как записать ints в память, но не понял, как прочитать их обратно.

import Control.Lens (zoom)
import System.IO (IOMode(..), withFile)
import Pipes
import qualified Pipes.Prelude as P
import qualified Pipes.ByteString as PB    
import qualified Pipes.Parse as P
import qualified Pipes.Binary as P

intStream :: Monad m => Proxy x' x () Int m b
intStream = go (0 :: Int) where
   go i = yield i >> go (i + 1)

decoder :: Monad m => Int ->  P.Parser P.ByteString m [Int]
decoder n = zoom (P.decoded . P.splitAt n) P.drawAll

main :: IO ()
main = do
    withFile "ints" WriteMode $ h -> do
         runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
    withFile "ints" ReadMode $ h -> do
         xs <- P.evalStateT (decoder 10000000) (PB.fromHandle h)
         print xs

я получил функцию декодера из документации для труб.Двоичный. Однако он использует drawAll, который согласно документация drawAll не является идиоматическим использованием труб и предоставляется для целей тестирования.

мой вопрос в том, как изменить decoder Так что он не использует drawAll и, таким образом, не загружает все значения xs в память. Поэтому вместо печати списка xs я мог бы P.map print над потоком декодированных ints чтение из файла.

1 ответов


врачи говорят, что decoded объектив из потока байтов в поток декодированных значений. Мы можем получить последнее из первого, используя view С lens:

decoder :: Monad m => Int -> Producer P.ByteString m a -> Producer Int m ()
decoder n p = void (view P.decoded p) >-> P.take n

main :: IO ()
main = do
    withFile "ints" WriteMode $ \h -> do
         runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
    withFile "ints" ReadMode $ \h -> do
         runEffect $ decoder 10000 (PB.fromHandle h) >-> P.print

у меня нет большого опыта работы с pipes, Я просто следовал за типами здесь. Хотя программа, похоже, работает так, как задумано.