在Haskell中解码/编码二进制小端数据的更好方法是什么?
考虑到endianness,消除Haskell中序列化/反序列化二进制数据的样板代码的最佳方法是什么?即,给定此结构:在Haskell中解码/编码二进制小端数据的更好方法是什么?,haskell,Haskell,考虑到endianness,消除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 实
data Foobar = Foobar { foo :: Word16, bar :: Word32 }
和派生的Data.Binary.Binary
类型类实例:
instance Binary Foobar where
get = do
foo <- get
bar <- get
return $ Foobar foo bar
实例二进制Foobar,其中
得到=做
foo您可以为不同的单词类型定义typeclass,例如:
class BinaryEndian a where
getEndian :: Get a
putEndian :: a -> Put
instance BinaryEndian Word16 where
getEndian = getWord16le
putEndian = putWord16le
等等
这可能会使代码编写起来更容易一些。如何定义单词的小尾端新类型
newtype LWord16 = LWord16 { unLWord16 :: Word16 }
newtype LWord32 = LWord32 { unLWord32 :: Word32 }
instance Binary LWord16 where get = LWord16 <$> getWord16le
instance Binary LWord32 where get = LWord32 <$> getWord32le
应该做正确的事情。二进制文件的预声明实例不总是big-endian吗?同时使用big和little endian看起来像是一种难以理解的错误。如果您想以预先存在的little endian二进制格式编写和解析数据,我建议您避免创建二进制实例,直接编写没有类型类的解析器和序列化程序。这很有效-谢谢!另外,generalizednewtypedering
在这种情况下非常有用;put=强制putWord16le
以避免调用fmap
的开销(可能非常小)。
data Foobar = Foobar { foo :: LWord16, bar :: LWord32 }