Note [Data con wrappers and GADT syntax]
Consider these two very similar data types:
data T1 a b = MkT1 b
data T2 a b where
MkT2 :: forall b a. b -> T2 a b
Despite their similar appearance, T2 will have a data con wrapper but T1 will
not. What sets them apart? The types of their constructors, which are:
MkT1 :: forall a b. b -> T1 a b
MkT2 :: forall b a. b -> T2 a b
MkT2's use of GADT syntax allows it to permute the order in which `a` and `b`
would normally appear. See Note [DataCon user type variable binders] in GHC.Core.DataCon
for further discussion on this topic.
The worker data cons for T1 and T2, however, both have types such that `a` is
expected to come before `b` as arguments. Because MkT2 permutes this order, it
needs a data con wrapper to swizzle around the type variables to be in the
order the worker expects.
A somewhat surprising consequence of this is that *newtypes* can have data con
wrappers! After all, a newtype can also be written with GADT syntax:
newtype T3 a b where
MkT3 :: forall b a. b -> T3 a b
Again, this needs a wrapper data con to reorder the type variables. It does
mean that this newtype constructor requires another level of indirection when
being called, but the inliner should make swift work of that. References 1
- DataCon user type variable binders GHC.Core.DataCon
Referenced by 3
- GHC.Core.DataCon call site
- The need for a wrapper GHC.Core.DataCon
- GHC.Types.Id.Make call site