Somebody asked me yesterday how to find out how big the runtime representation of a type is. I hacked this up using the internal unpackClosure# primitive:

{-# LANGUAGE MagicHash,UnboxedTuples #-} module Size where import GHC.Exts import Foreign unsafeSizeof :: a -> Int unsafeSizeof a = case unpackClosure# a of (# x, ptrs, nptrs #) -> sizeOf (undefined::Int) + -- one word for the header I# (sizeofByteArray# (unsafeCoerce# ptrs) +# sizeofByteArray# nptrs)

Try it in GHCi:

Prelude> :!ghc -c Size.hs Prelude> :l Size Ok, modules loaded: Size. Prelude Size> unsafeSizeof 3.3 16 Prelude Size> unsafeSizeof "a" 24 Prelude Size> unsafeSizeof (1,2,3,4) 40 Prelude Size> unsafeSizeof True 8 Prelude Size> unsafeSizeof $! Data.Complex.(:+) 2 3 24 Prelude Size> unsafeSizeof $! 3 16 Prelude Size> unsafeSizeof $! (3::Integer) 16 Prelude Size> unsafeSizeof $! (3::Int) 16 Prelude Size> unsafeSizeof $! (2^64::Integer) 24

I’m on a 64-bit machine, obviously. It doesn’t always do the right thing, but for ordinary algebraic types it should work most of the time. Remember to use $!, as the size returned for an unevaluated thunk is always just one word (unpackClosure# doesn’t work for thunks).