假设我有一个简单的类 AClass
,它有一个可以被覆盖的公共(public)成员 f1
。有什么方法可以用另一个成员 AClass
定义一个新的 f2
实例,而不是复制 AClass
的源代码?玩具代码如下:
class AClass a where
f1 :: a -> Int
data Val = I Int
instance AClass Val where
f1 x = 0
-- the method below can't be added as it is not public member of AClass
-- f2:: a -> Float
-- f2 x = 0.0
我环顾四周,但没有找到任何关于如何做到这一点的明确示例(即,我可以很好地理解示例 - 清晰度是相对的)。有哪些可能的方法?关闭,新类型声明还是其他什么?使用上面的玩具代码演示该技术会很有帮助 - 您可以更改
data
声明等(例如,将其替换为 newtype
周围的 Int
包装器),但上述代码中唯一不可变的是 AClass
的类声明。这是因为假设该类已经由库作者编写,因此,我无法触及它。最终结果应该是另一个玩具代码,它继承了 AClass
的优点,并添加了 f2
成员。当然,在像这样的覆盖类中会有一些警告。但是,它有助于了解什么是可能的,以及如何。
-- 更新 --
下面的工作代码 - 感谢 Ben 和 mergeconflict 提出解决方案 - 几乎没有遗漏的部分 - 填写如下:
class AClass a where
f1 :: a -> Int
class (AClass a) => BClass a where
f2 :: a -> Float
data Val = I Int
instance AClass Val where
f1 _ = 0
instance BClass Val where
f2 _ = 0.0
最佳答案
你想达到什么目的?
您有一个 Val
类型,它是 AClass
的一个实例。您可以定义任意数量的使用 Val
的函数,这些函数与类无关。停止尝试在 instance
声明中定义它们。
如果您期望能够拥有一个具有额外 AClass
函数的 f2
特定实例,然后您在使用 AClass
实例的函数中使用该实例并让它们能够调用 f2
......那是荒谬的。根据定义,所有 AClass
实例唯一已知的东西是在 AClass
中声明的东西。如果您只知道某个值是 AClass
实例类型的成员,那么您无法对它执行任何操作,而不能对 AClass
的所有实例执行任何操作。您不能调用任何特定于某些实例的额外内容。
如果您想创建一个新类,该类支持 AClass
和 f2
所做的所有操作,并且让 Val
成为该新类的实例……那么您只需这样做。
class AClass a => AnotherClass a where
f2 :: a -> Float
instance AnotherClass Val where
f2 x = 0.0
关于haskell - 用新成员覆盖类实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8514527/