NikitaBaksalyar
NikitaBaksalyar

Reputation: 2514

What is a better way to decode/encode binary little endian data in Haskell?

What is a best approach to get rid of a boilerplate code that serializes/deserializes binary data in Haskell, taking endianness into account? I.e., given this struct:

data Foobar = Foobar { foo :: Word16, bar :: Word32 }

And derived Data.Binary.Binary type class instance:

instance Binary Foobar where
  get = do
    foo <- get
    bar <- get
    return $ Foobar foo bar

decode stream :: Foobar treats the data as big endian.

Obvious way is to use getWord16le/getWord32le functions, but it involves lots of manual work (which could be automatically and nicely done by Template Haskell coupled with derive).

Perhaps, parametrized types are the solution?

Upvotes: 4

Views: 906

Answers (2)

Daniel Wagner
Daniel Wagner

Reputation: 153342

How about defining little-endian newtypes for words?

newtype LWord16 = LWord16 { unLWord16 :: Word16 }
newtype LWord32 = LWord32 { unLWord32 :: Word32 }
instance Binary LWord16 where get = LWord16 <$> getWord16le
instance Binary LWord32 where get = LWord32 <$> getWord32le

Then deriving Binary for the definition

data Foobar = Foobar { foo :: LWord16, bar :: LWord32 }

should do the right thing.

Upvotes: 8

Tener
Tener

Reputation: 5279

You can define a typeclass for different Word types, such as:

class BinaryEndian a where
   getEndian :: Get a
   putEndian :: a -> Put

instance BinaryEndian Word16 where
   getEndian = getWord16le
   putEndian = putWord16le

etc.

That would make TH code perhaps a little easier to write.

Upvotes: 2

Related Questions