6

我正在尝试在常量内存中读写很多整数。我已经弄清楚如何将整数写入内存,但还没有弄清楚如何将它们读回。

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的文档中获得了解码器功能。但是drawAll,根据文档 drawAll,它使用的不是管道的惯用用法,而是出于测试目的而提供的。

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

4

1 回答 1

6

文档说这decoded是从字节流到解码值流的镜头。我们可以使用viewfrom将后者从前者中取出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,我只是按照这里的类型。该程序似乎按预期运行。

于 2015-07-22T17:51:47.997 回答