Const versions of sizeOf and alignment (Was: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize`)

Henning Thielemann lemming at
Tue Dec 19 09:17:30 UTC 2017

On Wed, 13 Dec 2017, David Feuer wrote:

> +1, but we should also do this for sizeOf and alignment in Foreign.Storable.

If Storable would be intended for tuples, too, and there would be no 
padding, we could use special Monoids in Const, like so:

class Storable a where
    sizeOf :: Const (Sum Int) a
    alignment :: Const (LCM Int) a

instance (Storable a, Storable b) => Storable (a,b) where
    sizeOf = liftA2 (,) sizeOf sizeOf
    alignment = liftA2 (,) alignment alignment

Taking alignment into account we could define

data SizeAlign = SignAlign {sizeOf_, alignment_ :: Int}

instance Monoid SizeAlign where
    mempty = SizeAlign 0 1
    mappend x y =
          (sizeOf_ x + mod (- sizeOf_ x) (alignment_ y) + sizeOf_ y)
          (lcm (alignment_ x) (alignment_ y))

class Storable a where
    sizeAlign :: Const SizeAlign a

instance (Storable a, Storable b) => Storable (a,b) where
    sizealign = liftA2 (,) sizeOf sizeOf

However, SizeAlign.mappend this way is not valid because it violates 
associativity (e.g. sizes 1, 1, 2 with corresponding alignments). Even if 
it would be valid, it would still differ e.g. from Linux-x86 ABI, since 
structs are already padded to the next aligned size.

At least for the alignments an LCM monoid would work.

More information about the Libraries mailing list