Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy binary get

Why is Data.Binary.Get isn't lazy as it says? Or am I doing something wrong here?

import Data.ByteString.Lazy (pack)
import Data.Binary.Get (runGet, isEmpty, getWord8)

getWords = do
  empty <- isEmpty
  if empty
    then return []
    else do
      w <- getWord8
      ws <- getWords
      return $ w:ws

main = print $ take 10 $ runGet getWords $ pack $ repeat 1

This main function just hangs instead of printing 10 words.

like image 480
swish Avatar asked Apr 20 '13 10:04

swish


1 Answers

The documentation you linked provides several examples. The first one needs to read all the input before it can return and looks a lot like what you have written. The second one is a left-fold and processes the input in a streaming fashion. Here's your code rewritten in this style:

module Main where

import Data.Word (Word8)
import qualified Data.ByteString.Lazy as BL
import Data.Binary.Get (runGetState, getWord8)

getWords :: BL.ByteString -> [Word8]
getWords input
   | BL.null input = []
   | otherwise =
      let (w, rest, _) = runGetState getWord8 input 0
      in w : getWords rest

main :: IO ()
main = print . take 10 . getWords . BL.pack . repeat $ 1

Testing:

*Main> :main
[1,1,1,1,1,1,1,1,1,1]
like image 74
Mikhail Glushenkov Avatar answered Nov 10 '22 15:11

Mikhail Glushenkov