2015-07-22 9 views
6

Ich versuche zu lesen und schreiben sehr viele Ints in konstantem Speicher. Ich habe herausgefunden, wie man die Ints in den Speicher schreibt, aber ich habe nicht herausgefunden, wie man sie liest.Verwenden von Pipes zum Lesen und Schreiben von Binärdaten 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 

Ich habe die Decoder-Funktion aus der Dokumentation für Pipes.Binary. Es verwendet jedoch drawAll, die nach der documentationdrawAll nicht idiomatische Verwendung von Pipes ist und für Testzwecke zur Verfügung gestellt wird.

Meine Frage ist, wie Sie decoder ändern, so dass es drawAll nicht verwendet und somit nicht alle Werte von xs in den Speicher lädt. Anstatt also die Liste von xs zu drucken, konnte ich P.map print über einen Strom decodierten ints aus der Datei lesen.

Antwort

6

Die Dokumentation sagt, dass decoded ist ein Objektiv aus einem Strom von Bytes zu einem Strom von decodierten Werten. Wir können diesen aus der ehemaligen erhalten mit view von 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 

ich mit pipes nicht viel Erfahrung haben, folgte ich nur die Typen hier. Das Programm scheint jedoch wie beabsichtigt zu funktionieren.

+0

Ich versuche, den Typen zu folgen, aber manchmal wird es schwierig, wenn die Typen wie Alphabetsuppe aussehen;) –