[Haskell-cafe] Data.Binary suboptimal instance

Khudyakov Alexey alexey.skladnoy at gmail.com
Fri May 22 17:36:24 EDT 2009


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
> 
> -- | Read list of values from bytestring until it ends.
> getStream :: Get a -> Get [a]
> getStream getter = do
>   empty <- isEmpty
>   if empty
>     then return []
>     else do x <- getter
>             xs <- getStream getter
>             return (x:xs)
> 
> -- | Write list of values.
> putStream :: (a -> Put) -> [a] -> Put
> putStream f = mapM_ f

--
  Khudyakov Alexey


More information about the Haskell-Cafe mailing list