假设我正在编写一个 DSL,并希望同时支持幻像类型和错误类型的表达式。我的价值类型可能是
{-# LANGUAGE GADTs, DataKinds #-}
data Ty = Num | Bool deriving (Typeable)
data Val a where
VNum :: Int -> Val Num
VBool :: Bool -> Val Bool
我可以使用幻象擦除版本
{-# LANGUAGE ExistentialQuantification #-}
data Valunk = forall a . Valunk (V' a)
Valunk
现在,我可以通过case
删除两者来操作值,VNum
甚至VBool
以这种方式重新建立我的幻象类型
getNum :: Valunk -> Maybe (Val Num)
getNum (Valunk n@(VNum _)) = Just n
getNum _ = Nothing
但这只是感觉就像我正在重新实现Typeable
机器。不幸的是,GHC 不会让我推导出一个Typeable
forVal
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
有没有办法绕过这个限制?我很想写
getIt :: Typeable a => Valunk -> Maybe (Val a)
getIt (Valunk v) = cast v
但现在我不得不求助于这样的机器
class Typeably b x where kast :: x a -> Maybe (x b)
instance Typeably Num Val where
kast n@(VNum _) = Just n
kast _ = Nothing
对于我所有的类型。