Как определить размер типа в Haskell?

Предположим, что я создал тип следующим образом:

data RequestAck = 
         RequestAck { ackOK :: Word32, ackMsgCode :: Word32 } 

Я вижу, что это 2 * 4 байта большой и сделать что-то постоянным.

Единственные проблемы в том, что, как только я добавлю поле в тип, мне нужно будет запомнить обновленную константу.

Есть ли функция, которая предоставит мне размер определенного типа, например, t -> Int?

Функция, которая приближается к тому, что я хочу,

gsize :: Data a => a -> Int

внутри модуля Data.Generics.Schemes, но я не хочу, чтобы мой тип был экземпляром Data.

Существует ли более общее решение?

Конечно, я ищу функцию, которая работает с статическим типом, например, я не хочу передавать экземпляр, но сам тип.

Ответ 1

Это действительно зависит от того, как вы превращаете это в байты.

Как Word32, фиксированного размера нет. То, что вы видите как Word32, может быть непримененным закрытием, занимающим сотни мегабайт пространства. Или это может быть простой коробчатый тип (который будет больше 4 байтов). Или это может быть какой-то встроенный тегированный тип (в этом случае это зависит от платформы). Или это может быть отменено (в этом случае оно не существует).

Единственный раз, когда вы действительно можете сказать, какой размер выглядит так, это когда вы конвертируете в двоичный файл. Если вы делаете это для взаимодействия с FFI, вы можете использовать элемент sizeOf Foreign.Storable. Конечно, вам нужно написать экземпляр Storable для вашего типа, если вы хотите просто применить к нему sizeOf. Если вы сериализуете через Data.Binary... ну, просто сериализуйте вещь, действительно. Обычно вам не нужно заранее знать фактический размер (и если вы делаете это для заголовка размера, просто сериализуйте тело, которое вы подсчитаете размером во временную ленивую байтовую строку, затем возьмите размер, затем напишите размер и темп байтовой строки).

Ответ 2

bitSizeMaybe и finiteBitSize из Data.Bits предоставляют размер в битах. Они заменяют bitSize из того же модуля.

finiteBitSize :: b -> Int

Возвращает количество бит в типе аргумента. Настоящий значение аргумента игнорируется.

finiteBitSize = bitSize
bitSizeMaybe = Just . finiteBitSize

Пример использования:

> import Data.Bits
> finiteBitSize (42 :: Int)
64