I'm trying to understand what determines whether a type parameter must be nominal.
While GADTs and type familes seem different in the sense they are not "simple containers" as their instance definitions can "look at" their parameters, can simple types have obvious need for nominal parameters, like Set?
Should you be able to coerce?
coerce :: Coercible a b => F a -> F b
If not, then the argument of F
should be nominal.
In the case of Set
its first role is nominal
type role Set nominal
because we don't want
coerce :: Set Int -> Set ReversedInt
because newtype ReversedInt = RevInt Int deriving (Eq, Ord) via Data.Ord.Down Int
has a completely different Ord
than Int
and the internal structure of Set
depends on the ordering of its elements. Same for Map
type role Map nominal representational
For a GADT like
data F :: Type -> Type where
FInt :: F Int
we have a single inhabitant, so we don't want to allow
coerce :: F Int -> F ReversedInt
So, GHC infers type role F nominal
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With