我尝试写一些Haskell代码,其中有多种数据类型,每一种都可以有多种实现。 要做到这一点,我定义每种数据类型的class
,它的方法是相关构造函数和选择,然后实现在给定的构造函数和选择方面对类的成员的所有操作。
例如,或许A
是多项式类(方法getCoefficients
和makePolynomial
),其可以具有表示作为SparsePoly
或DensePoly
和B
是复数类(方法getReal
, getImag
和makeComplex
),其可以被表示为ComplexCartesian
或ComplexPolar
。
我抄录如下小例子。 我有两个班A
和B
各自有一个实现。 我想使这两个类的所有实例进入的情况下, Num
自动(这需要FlexibleInstances
和UndecidableInstances
类型扩展名)。 这工作得很好,当我只有一个A
或B
,但是当我试图用两个编译,我得到以下错误:
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
我想的是,“重复实例声明”消息是因为一个数据类型可以由两者的实例A
和B
。 我希望能够做出一个承诺,我不会那么做的,或者可能指定默认的类在一个类型既是类的实例的情况下使用编译器。
有没有办法做到这一点(也许另一种类型的扩展名?),或者这个东西,我坚持了?
这里是我的代码:
{-# 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
编辑:为了使自己清楚,我不是要写使用这种技术的任何实际的代码。 我在做一个练习,以帮助自己了解的类型系统和扩展更好。