Scala 逆变类型上的方法继承
我定义了两个类型类:Scala 逆变类型上的方法继承,scala,typeclass,contravariance,Scala,Typeclass,Contravariance,我定义了两个类型类: trait-WeakOrder[-X]{self=> def cmp(x:x,y:x):整数 def最大值[Y=0)x其他Y def最小值[Y def sup(x:x,y:x):x=最大值(x,y) def inf(x:x,y:x):x=min(x,y) } 但这是不可能的,因为逆变类型X出现在协变位置(返回值sup和inf) 但是,从语义上讲,这是正确的:max和min带有类型签名max[Y] def sup[Y这在语义上是不正确的。从协变和逆变的定义来看应该很清楚,但
trait-WeakOrder[-X]{self=>
def cmp(x:x,y:x):整数
def最大值[Y=0)x其他Y
def最小值[Y
def sup(x:x,y:x):x=最大值(x,y)
def inf(x:x,y:x):x=min(x,y)
}
但这是不可能的,因为逆变类型X
出现在协变位置(返回值sup
和inf
)
但是,从语义上讲,这是正确的:max
和min
带有类型签名max[Y]
def sup[Y这在语义上是不正确的。从协变和逆变的定义来看应该很清楚,但我将尝试给出一个示例:
假设我们有实体的层次结构:
class Shape(s:Float)
class Circle(r:Float) extends Shape(Math.PI.toFloat * r * r)
我们假设可以创建逆变式订单,就像您尝试的那样:
trait CircleOrder extends TotalOrder[Circle] {
// compare by r
}
trait ShapeOrder extends TotalOrder[Shape] {
// compare by s
}
根据反变式的定义,如Shape,我理解你所说的,这就是我通过签名max试图做到的[Y@TongfeiChen制作a型逆变意味着你需要有这样的可能性:val cOrd:CircleOrderByR=new ShapeOrderByS
。你确定这就是你需要的吗?我认为不同的顺序应该是不相关的。根据数学定义,总顺序是一个反对称的顺序c、 传递和总计。总计意味着每两个元素都可以比较。总计顺序仅依赖于一个函数cmp
(带签名(X,X)=>Int)来定义,因此它自然是逆变的。例如,实数的总计顺序(Double)自然意味着整数的总计顺序(Int)@TongfeiChen那么你是说,实现TotalOrder[Circle]
我们可以使用的是找到最多两个形状
?Circle
def clientMethod(circleOrder:TotalOrder[Circle]) = {
val maxCircle = circleOrder.max(???, ???) // expected to return Circle
maxCircle.r // accessing field that is present only in circle
}
clientMethod(new ShapeOrder {/*...*/})
trait WeakOrder[-X] {
def cmp(x: X, y: X): Int
def max[T](x: X with T, y: X with T): T =
if (cmp(x, y) >= 0) x else y
def min[T](x: X with T, y: X with T): T =
if (cmp(x, y) <= 0) x else y
}
trait Lattice[X] {
def sup[T](x: X with T, y: X with T): T
def inf[T](x: X with T, y: X with T): T
}
trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] {
def sup[T](x: X with T, y: X with T): T = max(x, y)
def inf[T](x: X with T, y: X with T): T = min(x, y)
}