2010-11-17 15 views
5

örnek bildirimleri bağlamında tür kısıtlamaları ekleme Ağırlıklı kenarları temsil etmeye çalışıyorum. Sonunda, EQ ve Ord'nin bir örneği olması için OutE'nin Eq ve Ord örneğinin olmasını istiyorum. temp.hs olarak varsayalım ben şu var file:Haskell

data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

applyFunBy accessor ordfun = (\x y -> (ordfun (accessor x) (accessor y))) 

instance Eq (OutE vtype etype) where 
    --(==) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    --(/=) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

ben GHCi bu yüklediğinizde, aşağıdaki hataları alıyorum: tip imzalar için çizgiler içeriyorsa

temp.hs:10:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:10:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (==) 
    In the definition of `==': == = applyFunBy edgeValue (==) 

temp.hs:11:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:11:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (/=) 
    In the definition of `/=': /= = applyFunBy edgeValue (/=) 
Failed, modules loaded: none. 

(==) ve (\ =), alıyorum:

temp.hs:6:1: 
    Misplaced type signature: 
    == :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

temp.hs:7:1: 
    Misplaced type signature: 
    /= :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

cevap

5

Sen etype sınırlı OutE ait Definition içinde Ord olmak:

data (Ord etype) => OutE vtype etype = ... 

Ama Eq durumda

, aslında unrestrictedly herhangi etype için örneği tanımlamak için çalışıyoruz.

instance Eq (OutE vtype etype) where 

Tabii bu nedenle siz de örnek tanımına typeclass kısıtlama eklemek gerekecek, kendisi sadece Ord etype s için tanımlanan OutE beri çalışmıyor.

== veya /= maddenin birinin tanımı typeclass çalışması için yeterli olan Not bu
instance (Ord etype) => Eq (OutE vtype etype) where 

. o ama sadece örnekleri/aslında typeclass işlevselliğini gerektiren yöntemler üzerinde, genellikle daha kolaydır ve bu nedenle daha iyi stil data -types üzerinde typeclass kısıtlamaları olmadığı varsayılabilir olduğunu


Not. Bir çok durumda, bir kısıtlamaya ihtiyaç duymaz ve gereksiz yere gereksiz tip imzalarla sona erer.

Örnek olarak, örn. Bazı düzenli harita tipi Ord key => Map key value.

Sadece tüm anahtarları listelemek istersek? Ya da elemanların sayısını? Biz bunlar için Ord olmak anahtarlarına ihtiyacım yok, o halde neden sadece basit

getKeys :: Map key value -> [key] 
getLength :: Map key value -> Int 

ile sınırsız harita bırakmaz ve sadece

insert :: Ord key => key -> value -> Map key value 
2
data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

İlk yayın: Bu kötü stil consdered edilir. Veri türü beyanlarınızın kısıtlamaları olmamalıdır. Kısıtlamaları, kapsayıcı paketinin yaptığı gibi, işlevlere bırakın. Ikinci "sorun". Veri beyanınızdan sonra deriving (Eq)'u ekleyebilirsiniz. Ben ... Bunu biliyor ve (sizin için iyi) kendi öğrenme için açıkça örneğini yazıyoruz tahmin ediyorum

instance Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

Üçüncü mesele: onlar Eq sınıfın olup olmadığını eşitlik değerlerini karşılaştırmak olamaz . Yani etype Denk kısıtlanır söylemek istiyorum:

instance (Eq etype) => Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

Dördüncüsü, aslında her ikisi (==) ve (/ =) için bir örneğini yazmaya gerek yoktur. Varsayılanları bunlardan birini tanımladığınızda çalışır.

+0

gibi bir işlevde gerçekten ihtiyacınız olduğunda typeclass eklerim '' türetme (Eq) '** tüm ** kayıt alanlarına dayalı eşitlik operatörleri oluşturacaktır (ve böylece“ Eq vtype ”ile hantal bir“ Eq ”örneği üretecektir), soruda verilen açık örnek sadece“ edgeValue ”ile karşılaştırılır. '. – Dario

+0

Doğru, o yazdıktan sonra bunu yaptıklarını farketmedim. Bunu işaret ettiğin için teşekkürler. –