Допустим, я пишу 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
для 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
Есть ли способ обойти это ограничение? я бы хотел написать
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
для всех моих видов.
deriving (Typeable)
еще не приспособлен для работы сDataKinds
.DataKinds
не дает вам ничего удивительного, просто дополнительная проверка. Вы можете использоватьdata Num
иdata Bool
вместо своего видаTy
. - person luqui   schedule 08.08.2013