[Haskell-cafe] Data.Binary suboptimal instance

Henning Thielemann lemming at henning-thielemann.de
Sat May 23 12:00:25 EDT 2009

Khudyakov Alexey schrieb:
> On Friday 22 May 2009 23:34:50 Henning Thielemann wrote:
>>> So lately I've been working on a little program to generate trippy
>>> graphics. (Indeed, some of you may remember it from a few years back...)
>>> Anyway, getting to the point, I just restructured my program. As part of
>>> the restructuring, I got rid of all the jiggery-pokery with
>>> Data.Array.Storable and so forth and decided to use Data.Binary.
>>> My first problem was quite simple. I want to write a program that reads
>>> an item from the input file, processes it, writes it to the output file,
>>> and repeats until the input file is empty. Data.Binary doesn't appear to
>>> provide any obvious way to do this. You can't be in the Get and Put
>>> monads simultaneously, and I can't figure out how to interleave them.
>> You can! - It's again time to point out that Put shouldn't be a monad, but
>> a monoid. But as it is, Put is a Writer monad on top of the Builder
>> monoid. Better use that Builder monoid directly.
> Could you elaborate? I didn't quite understand. 
> Anyway I had similar problem and simply wrote few functions. They 
> encode/decode values of same type element by element. It's lazy enough so code 
> could be written in following style: 
>> process :: [Foo] -> [Bar]
>> foo = readFile name 
>>        >>= writeFile out . encodeStream . process . decodeProcess
> There is a code. It is fast and worked for me without a problem. 
>> -- | Decode records in repetition
>> decodeStream :: Binary a => ByteString -> [a]
>> decodeStream = runGet (getStream get)
>> -- | Encode list of records as bytestring
>> encodeStream :: Binary a => [a] -> ByteString 
>> encodeStream = runPut . putStream put

I think the list should be avoided at all costs, because it is so slow.
I don't know if it is fused away by clever optimizer rules in the binary
package. Anyway, you can treat a Builder like a list. Just replace (++)
by 'mappend' and [] by 'mempty'.

It should work like this:

   do a <- getWord8
      b <- getWord8
      return $ Builder.singleton a `mappend` Builder.singleton b

More information about the Haskell-Cafe mailing list