Skip to content

Typeable evidence is always CAFfy

It turns out that Typeable's TypeRep evidence, which ends up being quite widely used in the exception machinery and elsewhere, produces gobs of CAFs. For instance, consider the case of typeRep @Int. Today this will result in the evidence binding:

tr :: TypeRep Int
tr = Data.Typeable.Internal.mkTrCon $tcInt []

After being floated to the top-level (as it very likely will be) this binding is, of course, a CAF. However, on examining the definition of mkTrCon one might suspect that this could be easily reduced to a static constructor application:

mkTrCon :: forall k (a :: k). TyCon -> [SomeTypeRep] -> TypeRep a
mkTrCon tc kind_vars
  = TrTyCon
    { trTyConFingerprint = fpr
    , trTyCon = tc
    , trKindVars = kind_vars
    , trTyConKind = kind }
  where
    fpr_tc  = tyConFingerprint tc
    fpr_kvs = map someTypeRepFingerprint kind_vars
    fpr     = fingerprintFingerprints (fpr_tc:fpr_kvs)
    kind    = unsafeCoerceRep $ tyConKind tc kind_vars

Nearly all of this computation can, in principle, be done at compile-time:

  • trTyConFingerprint is simply a fold over a known list
  • trTyCon is the TyCon itself
  • trKindVars is simply the given list of kind variables
  • trTyConKind is a bit tricky as it instantiates the tycon's KindRep. However, in the case of a kind-monomorphic type this instantiation is trivial.
Edited by Ben Gamari
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information