什么是最好的方法来摆脱在Haskell中序列化/反序列化二进制数据的样板代码,考虑到字节序?即,给出这个结构:
data Foobar = Foobar { foo :: Word16, bar :: Word32 }
派生Data.Binary.Binary
类型类实例:
instance Binary Foobar where
get = do
foo <- get
bar <- get
return $ Foobar foo bar
decode stream :: Foobar
将数据视为大端。
明显的方法是使用getWord16le
/ getWord32le
函数,但它涉及大量的手工工作(可以通过模板Haskell与derive一起自动完成)。
也许,参数化类型是解决方案?
答案 0 :(得分:8)
如何为单词定义little-endian newtypes?
newtype LWord16 = LWord16 { unLWord16 :: Word16 }
newtype LWord32 = LWord32 { unLWord32 :: Word32 }
instance Binary LWord16 where get = LWord16 <$> getWord16le
instance Binary LWord32 where get = LWord32 <$> getWord32le
然后为定义导出Binary
data Foobar = Foobar { foo :: LWord16, bar :: LWord32 }
应该做正确的事。
答案 1 :(得分:2)
您可以为不同的Word类型定义类型类,例如:
class BinaryEndian a where
getEndian :: Get a
putEndian :: a -> Put
instance BinaryEndian Word16 where
getEndian = getWord16le
putEndian = putWord16le
等
这会使TH代码更容易编写。