newtype
with poly-kinded photom types
These days, PolyKinds
and RankNTypes
extensions are enabled by default with GHC2024
. The former makes types poly-kinded as much as possible, which can cause some weird errors.
Imagine that you have a newtype
X
.
newtype X a = X a
You can declare another newtype
Y
to wrap it.
newtype Y a = Y (X a)
But when you add a phantom type s
to X
,
newtype X s a = X a
The compiler refuses Y
which uses a rank-n type
newtype Y a = Y (forall s. X s a)
with this error.
<interactive>:1:15: error: [GHC-07525]
• A newtype constructor must not have existential type variables
Y :: forall a {k}. (forall (s :: k). X s a) -> Y a
• In the definition of data constructor ‘Y’
In the newtype declaration for ‘Y’
This looks weird because you didn’t use any existential type variables.
This happens because s
is poly-kinded. When you check :t X
in GHCi, you’ll find that s
has an invisible kind k
implicitly.
> :t X
X :: forall {k} (s :: k) a. a -> X s a
Since this kind isn’t declared explicitly in Y
, it makes GHC infer a type of Y
as
newtype Y a = forall k. Y (forall (s :: k). X s a)
as the error message suggested, which makes k
an existential type variable.
You can avoid this by declaring k
explicitly along with s
to make it not an existential variable.
newtype Y a = Y (forall k s. X (s :: k) a)