Thorsten Lorenz
Thorsten Lorenz

Reputation: 11847

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.

Upvotes: 19

Views: 4742

Answers (2)

wsaleem
wsaleem

Reputation: 642

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

Upvotes: 3

bdonlan
bdonlan

Reputation: 231123

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).

Upvotes: 15

Related Questions