Diciamo che sto scrivendo una DSL e voglio avere supporto sia per il supporto di tipo fantasma che per le espressioni mal digitate. I miei tipi di valore potrebbero essereGADT cast in modo normale
{-# LANGUAGE GADTs, DataKinds #-}
data Ty = Num | Bool deriving (Typeable)
data Val a where
VNum :: Int -> Val Num
VBool :: Bool -> Val Bool
e posso lavorare con un fantasma cancellata versione
{-# LANGUAGE ExistentialQuantification #-}
data Valunk = forall a . Valunk (V' a)
Ora, posso operare su valori di Valunk
da case
ing fuori sia VNum
e VBool
e anche ristabilire il mio fantasma tipi in questo modo
getNum :: Valunk -> Maybe (Val Num)
getNum (Valunk [email protected](VNum _)) = Just n
getNum _ = Nothing
Ma questo mi sembra di reimplementare lo Typeable
macchinario. Purtroppo, GHC non mi permette di ricavare una Typeable
per 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
C'è un modo per aggirare questa limitazione? Mi piacerebbe scrivere
getIt :: Typeable a => Valunk -> Maybe (Val a)
getIt (Valunk v) = cast v
ma adesso devo ricorrere a macchinari come questo
class Typeably b x where kast :: x a -> Maybe (x b)
instance Typeably Num Val where
kast [email protected](VNum _) = Just n
kast _ = Nothing
per tutti i miei tipi.
E loo ks come il meccanismo 'derivante (tipizzabile)' non è ancora stato fatto per funzionare con 'DataKinds'. 'DataKinds' non ti dà niente di straordinario, solo un piccolo controllo extra. Puoi usare 'data Num' e' data Bool' invece del tuo tipo 'Ty'. – luqui