[Haskell-cafe] Re: Data.Binary and little endian encoding

John Lato jwlato at gmail.com
Fri May 15 05:16:58 EDT 2009

> On Thu, May 14, 2009 at 8:46 PM, Don Stewart <dons at galois.com> wrote:
>> leimy2k:
>> >
>> >
>> > On Thu, May 14, 2009 at 8:40 PM, Don Stewart <dons at galois.com> wrote:
>> >
>> >     leimy2k:
>> >     > I actually need little endian encoding... wondering if anyone else
>> hit
>> >     this
>> >     > with Data.Binary. (because I'm working with Bell Lab's 9P protocol
>> which
>> >     does
>> >     > encode things on the network in little-endian order).
>> >     >
>> >     > Anyone got some "tricks" for this?
>> >
>> >     Yes!
>> >     There are big, little and host-endian primitives in the Get/Put
>> monads.
>> >
>> >
>> http://hackage.haskell.org/packages/archive/binary/
>> >     Data-Binary-Put.html#v%3AputWord16le
>> >
>> >     You can use these to build encoders directly.
>> >
>> >
>> > Cool... I just have to write my own encoder and decoder now.
>> >
>> > As a request could we get encodeLe decodeLe for a later version of this
>> > library?  :-)  That'd be totally awesome.
>> Oh, you mean entirely different instances for all the current ones, that
>> use LE encodings?
> Well the library is leaning towards "Network Byte Order" in that it has
> encode/decode that only encode/decode for Big Endian.
> Us folks who have to do little endian all now have to write our own
> encoding/decoding :-)
> I'm speaking specifically of the encode/decode functions.  I have no idea
> how they're implemented.

The encode/decode functions just call the runGet/runPut functions for
whatever is being encoded or decoded to combined with the get/put
functions from the Binary instance.  The endian-ness is entirely
determined by the Binary instance for the data type you're
encoding/decoding, not anything in the encode/decode functions

For data types you define, you can make the Binary instance LE
standard (although it may not be a good idea) by using the
little-endian primitives Don mentioned.  For built-in types, if you
want to use a different endian-ness, you can make new get/put
functions then call runGet/runPut on those directly.  You won't be
able to redefine the Binary instances, but if you'll be doing this
with a lot of different types you could make your own BinaryLE class
like this:

class BinaryLE t where
  putLE :: t -> Put
  getLE :: Get t

encodeLE :: BinaryLE a => a -> ByteString
encodeLE = runPut . putLE

decodeLE :: BinaryLE a => ByteString -> a
decodeLE = runGet getLE

I've done some work with Binary and little-endian, and this bias never
really bothered me (I think it's actually a host-endian bias, could be
mistaken).  I was using my own data types so I had to make my own
custom Binary instances, which I would have had to do anyway.  The
data format specified little-endian, so making the Binary instance
LE-standard seemed appropriate.

You'd only need to re-make custom get/put functions if you're using
types that already have Binary instances, and you intend to manipulate
the data outside of Haskell.  Does that describe your situation?


More information about the Haskell-Cafe mailing list