Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 469
NikitaBaksalyar Avatar asked Dec 28 '22 11:12

NikitaBaksalyar


2 Answers

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.

like image 131
Daniel Wagner Avatar answered Jan 25 '23 22:01

Daniel Wagner


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.

like image 26
Tener Avatar answered Jan 25 '23 23:01

Tener