Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine size of a type in Haskell?

Assume I created a type as follows:

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

I can see that it is 2 * 4 bytes big and make that a constant somewhere.

The only problems is that once I add a field to the type, I'd have to remember to update my constant.

Is there a function out there that will provide me with the size of a given type e.g., t -> Int?

The function that comes close to what I want is

gsize :: Data a => a -> Int

inside the Data.Generics.Schemes module, but I don't want to have to make my type an instance of Data.

Is there a more generic solution out there?

To be sure, I'm looking for a function that operates on the static type, e.g., I don't want to pass an instance, but the type itself.

like image 538
Thorsten Lorenz Avatar asked Feb 29 '12 02:02

Thorsten Lorenz


2 Answers

This really depends on how you're turning this into bytes.

As a Word32, there is no fixed size. What you see as a Word32 could be an unapplied closure taking up hundreds of megabytes of space. Or it could be a simple boxed type (which would be larger than 4 bytes). Or it could be some kind of inline tagged type (in which case it depends on the platform). Or it could be elided (in which case it doesn't exist).

The only time when you can really say what size something like this is is when you convert to binary. If you're doing this to interface with the FFI, you can use the sizeOf member of Foreign.Storable. Of course, you need to write a Storable instance for your type if you want to just apply sizeOf directly to it. If you're serializing via Data.Binary... well, just serialize the thing, really. You usually don't need to know the actual size beforehand (and if you do for a size header, just serialize the body you're counting the size of into a temporary lazy bytestring, then take the size, then write the size and temp bytestring).

like image 60
bdonlan Avatar answered Sep 25 '22 21:09

bdonlan


bitSizeMaybe and finiteBitSize from Data.Bits provide the size in bits. They supersede bitSize from the same module.

finiteBitSize :: b -> Int

Return the number of bits in the type of the argument. The actual value of the argument is ignored.

finiteBitSize = bitSize
bitSizeMaybe = Just . finiteBitSize

Example usage:

> import Data.Bits
> finiteBitSize (42 :: Int)
64
like image 25
wsaleem Avatar answered Sep 25 '22 21:09

wsaleem