当类型也位于另一个类中时,是否可以在类实例中提供方法的改进实现(也称为OOP中的重写)?或者至少,如果该其他类是子类。
我有一个C
带有methodm
的类S
,C
带有method的子类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
。嗯,不是,而是从面向对象的角度继承的。
出于特定目的,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
是因为改进非常明显。
这是一个好问题。要记住的一件事是,数据类型是否是类型类的实例仅是编译时的信息,即,我们始终能够在使用站点上使用静态可用信息来选择使用哪个实例,而多态性源于能够从上下文中选择一个实例。通常,如果您询问“是否是a
typeclass的成员B
?”,则只能获得“是”和“编译错误”的答案。(第二个观察值被改变了一点OverlappingInstances
,但对您的情况似乎没有帮助)
因此,您眼前的问题的答案是否定的。除非您是该类型类的方法,否则您不能对类型在类型类中的成员资格做出决定。我们可以做的就是将此决定添加为方法(使用constraints
软件包)
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
在第一种情况下,我们将CoherentModel b
在上下文中具有局部变量。挺酷的
太糟糕了,我们这里有一个表达问题,其中所有con
需要的不同实现都需要集中到一个地方。同样太糟糕的是,isCoherent
需要在每个连贯Model
实例上手动实现,与CoherentModel
实例所在的位置分开。
这里有很多值得探索的地方,但我必须走了。祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句