根据子类

时间:2018-05-26 13:42:58

标签: haskell typeclass method-overriding

当类型在另一个类中时,我是否可以在类实例中提供方法的精炼实现(也就是OOP中的覆盖)?或者至少,如果那个其他类是子类。

我有一个方法C的课程mS的子类C方法s和类型T a所以那里是实例化

class C a where m :: [a] -> Bool
class C a => S a where s :: a -> a -> Bool
instance C a => C (T a) where m = ...
instance S a => S (T a) where s = ...
像往常一样。 现在碰巧是当T a在子类中时(我不知道它依赖于a),方法m可以更有效地实现(二次与指数时间) )使用s

我试过'覆盖'实施中的m

instance S a => S (T a) where
    s = ...
    m = (all . uncurry) (=^=) . pairs -- override C.m

但编译器错误主要是因为m不是S的公共方法。嗯,它不是,但它是在OO意义上继承的。

出于特定目的,m的专用版本可用于所有实例;它不是在任何地方被覆盖的默认值。

编辑:因为请求,具体代码有一点解释。

我有一个类Model,其中包含(以及其他)方法con,用于检查列表的一致性。

class Model a where
    con :: [a] -> Bool

两个模型可以形成箭头模型。

data Arrow a b = [a] :->: b
lhs w = [ a | (u :->: _) <- w, a <- u ]
rhs w = [ b | (_ :->: b) <- w ]

对于特定实例Model (Arrow a b),常规con实施非常昂贵(请在定义中注明powerset)。

instance (Model a, Model b) => Model (Arrow a b) where
    con w = all (\w' -> con (lhs w') `implies` con (rhs w')) (powerset w)

CoherentModel的子类Model有一个方法(=^=),用于检查两个对象的一致性。相干模型的条件是,如果所有对都是列表,则列表是一致的。

class Model a => CoherentModel a where
    (=^=) :: a -> a -> Bool
    a =^= b = con [a, b]

此类CoherentModel此时的文档数量多于功能。

因此,鉴于模型是连贯的,一致性更有效率。

instance (Model a, CoherentModel b) => CoherentModel (Arrow a b) where
    (u :->: a) =^= (v :->: b) = con (u ++ v) `implies` a =^= b

在这种情况下,con可以使用

实现
con = (all . uncurry) (=^=) . pairs
  where
    pairs :: [a] -> [(a,a)]
    pairs [] = []
    pairs [_] = []
    pairs [x,y] = [(x,y)]
    pairs (x:xs) = map ((,) x) xs ++ pairs xs

但是我找不到指定这个的方法。它不仅适用于Arrow,而且与所有带参数的模型相关。我之所以选择Arrow是因为改进很重要。

1 个答案:

答案 0 :(得分:5)

这是一个很好的问题。要记住的一件事是数据类型是否是类型类的实例是仅编译时信息 - 即我们总是能够使用使用站点上的静态可用信息来选择使用哪个实例,多态性来自于能够从上下文中选择一个实例。一般来说,如果您问{4}是类别a的成员?&#34;,您可以获得的唯一答案是&#34;是&#34;和&#34;编译错误&#34;。 (第二个观察结果稍微改变了B,但它似乎对你的情况没有帮助)

因此,您当前问题的答案是。除非您是该类型类的方法,否则您无法对类型类中的类型成员资格做出决定。我们可以做的是将此决定添加为方法(使用constraints包)

OverlappingInstances

您可以通过以下方式轻松定义已实例化import Data.Constraint class Model a where con :: [a] -> Bool isCoherent :: Maybe (Dict (CoherentModel a)) isCoherent = Nothing 的任何类型:

CoherentModel

现在您可以像这样执行您的决定(带扩展名instance Model Foo where con = ... isCoherent = Just Dict ScopedTypeVariables):

TypeApplications

在第一种情况的正文中,我们将在上下文中有一个本地instance (Model a, Model b) => Model (Arrow a b) where con | Just Dict <- isCoherent @b = -- efficient implementation | otherwise = -- inefficient implementation 。这很酷。

太糟糕了,我们在这里有一种expression problemCoherentModel b的所有不同实现都需要收集到一个地方。同样太糟糕con需要在每个连贯的isCoherent实例上手动实现,与其Model实例的位置分开。

这里有很多值得探索但我必须去的地方。祝你好运!