Birden çok veri türü olan ve her biri birden fazla uygulama içeren bazı Haskell kodları yazmaya çalışıyorum. Bunu yapmak için, her bir veri tipini metodları ilgili kurucular ve seçiciler olan class
olarak tanımlarım ve daha sonra verilen kurucular ve seçiciler açısından o sınıfın üyeleri üzerindeki tüm işlemleri uygularım.Türleri ile eğlenceli! Birden çok örnek bildirimi çözümleniyor
Örneğin, belki de A
bir SparsePoly
veya DensePoly
ve B
gibi bir gösterimi olabilir (yöntem getCoefficients
ve makePolynomial
ile) polinom sınıftır olabilir (yöntem getReal
, getImag
ve makeComplex
) ile karmaşık bir sayı sınıfıdır ComplexCartesian
veya ComplexPolar
olarak temsil edilir.
Aşağıda minimal bir örnek ürettim. Her birinin bir uygulaması olan A
ve B
iki sınıfım var. Her iki sınıfın tüm örneklerini otomatik olarak Num
örneğine yapmak istiyorum (bu FlexibleInstances
ve UndecidableInstances
tür uzantılarını gerektirir). Sadece A
veya B
birine sahip olduğunda bu iyi çalışır, ancak her ikisi ile derlemeye çalıştığınızda, aşağıdaki hatayı alıyorum:
Duplicate instance declarations:
instance [overlap ok] (A a, Num x, Show (a x), Eq (a x)) =>
Num (a x)
-- Defined at test.hs:13:10-56
instance [overlap ok] (B b, Num x, Show (b x), Eq (b x)) =>
Num (b x)
-- Defined at test.hs:27:10-56
Ben 'yinelenen örneği beyanları' mesajı olduğunu varsayalım bir veri türü nedeniyle A
ve B
'un bir örneği yapılabilir. Derleyiciye bunu yapmayacağımı veya bir türün her iki sınıfın bir örneği olması durumunda kullanmak için varsayılan bir sınıf belirtebileceğine söz verebilmeyi istiyorum.
Bunu yapmanın bir yolu var mı (belki başka türde bir uzantıya mı?) Veya buna yapıştığım bir şey mi var?
İşte benim kod:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
class A a where
fa :: a x -> x
ga :: x -> a x
data AImpl x = AImpl x deriving (Eq,Show)
instance A AImpl where
fa (AImpl x) = x
ga x = AImpl x
instance (A a, Num x, Show (a x), Eq (a x)) => Num (a x) where
a1 + a2 = ga (fa a1 + fa a2)
-- other implementations go here
class B b where
fb :: b x -> x
gb :: x -> b x
data BImpl x = BImpl x deriving (Eq,Show)
instance B BImpl where
fb (BImpl x) = x
gb x = BImpl x
instance (B b, Num x, Show (b x), Eq (b x)) => Num (b x) where
-- implementations go here
Düzenleme: Yeterince açık hale getirmek için bu tekniği kullanarak herhangi pratik kod yazmak çalışmıyorum. Bunu, tip sistemini ve uzantıları daha iyi anlama konusunda yardımcı olmak için bir egzersiz olarak yapıyorum.
İlgili: [Yazım nasıl yazılır, eğer typeclass a, sonra da bu tanım ile b'nin bir örneğidir.]] (Http://stackoverflow.com/a/3216937/98117). – hammar