gpt4 book ai didi

scala - 逆变类型的方法继承

转载 作者:行者123 更新时间:2023-12-03 17:43:01 25 4
gpt4 key购买 nike

我定义了两个类型类:

trait WeakOrder[-X] { self =>
def cmp(x: X, y: X): Int
def max[Y <: X](x: Y, y: Y): Y = if (cmp(x, y) >= 0) x else y
def min[Y <: X](x: Y, y: Y): Y = if (cmp(x, y) <= 0) x else y
}

trait Lattice[X] { self =>
def sup(x: X, y: X): X
def inf(x: X, y: X): X
}

我想做以下事情:

trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
def sup(x: X, y: X): X = max(x, y)
def inf(x: X, y: X): X = min(x, y)
}

但这是不可能的,因为逆变类型 X出现在协变位置(返回值 supinf )。

然而,语义上这是正确的: maxmin带有类型签名 max[Y <: X](x: Y, y: Y): Y编码 max 的返回值这一事实/ min必须是两个参数之一。

我尝试执行以下操作:

trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
def sup[Y <: X](x: Y, y: Y): Y = max(x, y)
def inf[Y <: X](x: Y, y: Y): Y = min(x, y)
}

但是,该方法 def sup[Y <: X](x: Y, y: Y): Y不能继承 def sup[X](x: X, y: X): X .编译器提示类型签名不匹配。但是前一个(带有现场方差注释)比后一个签名施加了更强的类型限制。为什么前者不能继承后者?如何绕过 TotalOrder[-X] 上的逆变类型限制(语义上,全序是逆变的)?

最佳答案

这在语义上是不正确的。从协变和逆变的定义应该很清楚了,但我会尝试举一个例子:

假设我们有实体的层次结构:

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 <: Circle , CircleOrder <: ShapeOrder(CircleOrder 是 ShapeOrder 的父类(super class)型)

假设我们有一个以 CircleOrder 作为参数的客户
并用它来比较圆圈:
def clientMethod(circleOrder:TotalOrder[Circle]) = {
val maxCircle = circleOrder.max(???, ???) // expected to return Circle
maxCircle.r // accessing field that is present only in circle
}

那么,根据继承的定义,应该可以通过
ShapeOrder 而不是 CircleOrder(记住,ShapeOrder 是子类型):
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)
}

关于scala - 逆变类型的方法继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31665082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com