If I have a type constrained by a finite DataKind
{-# LANGUAGE DataKinds #-}
data K = A | B
data Ty (a :: K) = Ty { ... }
and an existential type which forgets the exact choice of K
in the type... but remembers it in a passed dictionary.
class AK (t :: K) where k :: Ty t -> K
instance AK A where k _ = A
instance AK B where k _ = B
data ATy where ATy :: AK a => Ty a -> ATy
it's genuinely the case that ATy <-> Either (Ty A) (Ty B)
, but if I want to write one of those witnesses I need to use unsafeCoerce
getATy :: ATy -> Either (Ty A) (Ty B)
getATy (ATy it) = case k it of
A -> Left (unsafeCoerce it)
B -> Right (unsafeCoerce it)
So generally this works—I can forget the choice of K
using ATy
and remember it partially using getATy
. Altogether this takes advantage of as much type information as I have available.
However, this type information feels as though it ought to be "obvious" if done correctly.
Is there a way to achieve the above without the use of unsafeCoerce
? Is there a way to get rid of that AK
constraint in the existential? Can this technique be performed based entirely off the information constraints provided by the data kind?
A -> Left Ty
? – IshiiK
type might be phantom, but it conveys a lot of information still. – WorkhouseAK
class doesn't compile with my GHC 7.8 becausek
's type doesn't mention any class type variable. – Superelevationa -> t
– Workhouse