假设我创建了一个类型如下:
data RequestAck =
RequestAck { ackOK :: Word32, ackMsgCode :: Word32 }
我可以看到它是2 * 4字节大,并使其在某处保持不变。
唯一的问题是,一旦我向该类型添加了一个字段,我就必须记得更新我的常量。
是否有一个功能可以为我提供给定类型的大小,例如t -> Int
?
接近我想要的功能是
gsize :: Data a => a -> Int
在Data.Generics.Schemes模块中,但我不想让我的类型成为Data
的实例。
那里有更通用的解决方案吗?
可以肯定的是,我正在寻找一个对静态类型进行操作的函数,例如,我不想传递实例,而是传递类型本身。
答案 0 :(得分:11)
这实际上取决于你如何将其变成字节。
作为Word32
,没有固定的尺寸。你所看到的Word32
可能是一个未应用的闭包,占用了数百兆的空间。或者它可以是一个简单的盒装类型(大于4个字节)。或者它可能是某种内联标记类型(在这种情况下,它取决于平台)。或者可以省略(在这种情况下不存在)。
当你真正说出这样的大小时,唯一的一次是当你转换成二进制时。如果您这样做是为了与FFI连接,您可以使用the sizeOf
member of Foreign.Storable
。当然,如果您想直接应用sizeOf
,则需要为您的类型编写一个可存储实例。如果你是通过Data.Binary进行序列化......那么,只需序列化这个东西,真的。你通常不需要事先知道实际的大小(如果你做一个大小的标题,只需序列化你正在计算的大小为一个临时的懒字节字符串,然后取大小,然后写大小和临时字节字符串)。
答案 1 :(得分:2)
bitSizeMaybe
和finiteBitSize
提供了位大小。他们从同一模块中取代bitSize
。
finiteBitSize :: b -> Int
返回参数类型中的位数。实际上 参数的值被忽略。
finiteBitSize = bitSize
bitSizeMaybe = Just . finiteBitSize
使用示例:
> import Data.Bits
> finiteBitSize (42 :: Int)
64