A question from yesterday had a definition of HList
(from the HList
package) that uses data families. Basically:
data family HList (l :: [*])
data instance HList '[] = HNil
newtype instance HList (x ': xs) = HCons1 (x, HList xs)
pattern HCons x xs = HCons1 (x, xs)
instead of the usual (IMO more elegant and intuitive) GADT definition
data HList (l :: [*]) where
HNil :: HList '[]
HCons :: x -> HList xs -> HList (x ': xs)
This is because the data family version lets us coerce (we only get to coerce the HList (x ': xs)
case since it is a newtype instance
, but that is enough), while the GADT infers only a nominal role for l
(thus blocking any coercion). (My answer to the mentioned question has a concrete example of this.)
The failings of the role system for GADTs with respect to HList
are discussed in this two year old question. Basically, GHC automatically marks any "GADT-like" type variable as nominal.
Given that some time has passed since then and there is talk of making roles more flexible around type/data families, is there any path forward (i.e. some existing idea, some open Trac ticket, anything really) for checking more interesting roles in GADTs (like HList
)? Are there some fundamental limitations here with GADTs or the interplay of DataKinds
and roles? What would need to be implemented/created for this to work?