[Haskell-cafe] Data.Binary suboptimal instance
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