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)
    }