
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