使用 Pipes 读写二进制数据 Haskell

Using Pipes to read and write binary data in Haskell

我正在尝试在常量内存中读取和写入非常多的整数。我已经想出如何将整数写入内存,但还没有想出如何读回它们。

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

我从 Pipes.Binary. However it uses drawAll which according to the documentation 的文档中获得了解码器功能 drawAll 不是管道的惯用用法,提供用于测试目的。

我的问题是如何修改 decoder 使其不使用 drawAll 从而不会将 xs 的所有值加载到内存中。因此,我可以 P.map print 在从文件中读取的解码 ints 流上打印 xs 列表。

文档说 decoded 是从字节流到解码值流的透镜。我们可以使用 view from 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没有太多经验,我只是跟着这里的类型。该程序似乎按预期运行。