Let's say I'm writing a DSL and want to have support for both phantom type support and badly typed expressions. My value types might be
{-# LANGUAGE GADTs, DataKinds #-}
data Ty = Num | Bool deriving (Typeable)
data Val a where
VNum :: Int -> Val Num
VBool :: Bool -> Val Bool
and I can work with an phantom erased version
{-# LANGUAGE ExistentialQuantification #-}
data Valunk = forall a . Valunk (V' a)
Now, I can operate on values of Valunk
by case
ing out both VNum
and VBool
and even reestablish my phantom types in this way
getNum :: Valunk -> Maybe (Val Num)
getNum (Valunk n@(VNum _)) = Just n
getNum _ = Nothing
But this just feels like I'm reimplementing the Typeable
machinery. Unfortunately, GHC won't let me derive a Typeable
for Val
src/Types/Core.hs:97:13:
Can't make a derived instance of `Typeable (Val a)':
Val must only have arguments of kind `*'
In the data declaration for Val
Is there a way to get around this restriction? I'd love to write
getIt :: Typeable a => Valunk -> Maybe (Val a)
getIt (Valunk v) = cast v
but right now I have to resort to machinery like this
class Typeably b x where kast :: x a -> Maybe (x b)
instance Typeably Num Val where
kast n@(VNum _) = Just n
kast _ = Nothing
for all of my types.