2013-08-07 17 views
9

Diyelim ki bir DSL yazıyor ve hem fantom desteği hem de yanlış yazılan ifadeler için destek istiyorum. Hem VNum ve VBool dışarı ing case tarafından Valunk değerleri üzerinde işlem ve hatta benim hayaleti yeniden edebilir, sürüm ŞimdiTipik olarak GADT'leri yayınlama

{-# LANGUAGE ExistentialQuantification #-} 

data Valunk = forall a . Valunk (V' a) 

My değer türleri

{-# LANGUAGE GADTs, DataKinds #-} 

data Ty = Num | Bool deriving (Typeable) 

data Val a where 
    VNum :: Int -> Val Num 
    VBool :: Bool -> Val Bool 

olabilir ve ben bir hayalet çalışabilirsiniz sildim Bu şekilde

getNum :: Valunk -> Maybe (Val Num) 
getNum (Valunk [email protected](VNum _)) = Just n 
getNum _     = Nothing 

yılında tipleri Amareimplementing gibiyim bu sadece hissediyormakineleri. Ne yazık ki, GHC bu sınırlamayı aşmanın bir yolu var mı bana TypeableVal

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 

için türetmek izin vermiyor? Ben

getIt :: Typeable a => Valunk -> Maybe (Val a) 
getIt (Valunk v) = cast v 

yazmak isterim ama şu anda benim türleri için bu

class Typeably b x where kast :: x a -> Maybe (x b) 
instance Typeably Num Val where 
    kast [email protected](VNum _) = Just n 
    kast _   = Nothing 

gibi makine başvurmak zorunda.

+0

It:

getIt :: Typeable a => Valunk -> Maybe (Val a) getIt (Valunk v) = gcast v 

Bu

ile test edildi türetme (Typeable) gibi ks henüz "DataKinds" ile çalışmaya başlamamıştır. 'DataKinds' size şaşırtıcı bir şey vermez, sadece biraz ekstra kontrol. 'Ty' türünüz yerine' data Num' ve 'data Bool' kullanabilirsiniz. – luqui

cevap

1

Kendi başına Data.Typeable türetebilirsiniz:

{-# LANGUAGE GADTs, DataKinds, DeriveDataTypeable, ExistentialQuantification #-} 

import Data.Typeable 

data Ty = TNum | TBool deriving Typeable 

data Valunk = forall a. Typeable a => Valunk a 

data Val a where 
    VInt :: Int -> Val TNum 
    VBool :: Bool -> Val TBool 

instance Show (Val a) where 
    show (VInt a) = show a 
    show (VBool a) = show a 

valtypenam = mkTyCon3 "package" "module" "Val" 

instance Typeable (Val a) where 
    typeOf _ = mkTyConApp valtypenam [] 

getIt :: Valunk -> Maybe (Val a) 
getIt (Valunk p) = cast p 

Bu olsun işlevini sağlayacaktır. Sadece türünüzü doğru bir şekilde yazdığınızdan emin olun (böylece paketi, modülü ve türü doğru bir şekilde yazın), aksi takdirde diğer paketler sorunlara yol açabilir.

Bu örneklerin nasıl yazılacağına dair daha fazla örnek için, aşağıdakilere bakın: Data.Derive.Typeable source.

DÜZENLEME: Kodda çok garip bir kopya ve geçmiş hata vardı, ancak şimdi çalışıyor. Bunu aldıktan sonra

data Valunk = forall a . Typeable a => Valunk (Val a) 

, sadece sizin için ne soruyorsun ulaşmak için gcast kullanabilirsiniz: Her şeyden

1

Önce, Valunk miktarsal tip Typeable olduğu bir şahit saklamak gerekir: tuvalet

data Val a where 
    VNum :: Int -> Val Int 
    VBool :: Bool -> Val Bool 
İlgili konular