当类型在另一个类中时,我是否可以在类实例中提供方法的精炼实现(也就是OOP中的覆盖)?或者至少,如果那个其他类是子类。
我有一个方法C
的课程m
,S
的子类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
是因为改进很重要。
答案 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 problem,CoherentModel b
的所有不同实现都需要收集到一个地方。同样太糟糕con
需要在每个连贯的isCoherent
实例上手动实现,与其Model
实例的位置分开。
这里有很多值得探索但我必须去的地方。祝你好运!