Scala中的协方差对方差误差

Scala中的协方差对方差误差,scala,covariance,Scala,Covariance,我试图编译以下代码: class A[-T] class B[-T] extends A[A[T]] 我得到以下错误: error: contravariant type T occurs in covariant position in type [-T]A[A[T]]{def <init>(): B[T]} of class B 错误:逆变型T出现在类B的类型[-T]A[A[T]{def():B[T]}的协变位置 为什么这是一个错误?是编译器定义的A(或B)的构造函数 代码

我试图编译以下代码:

class A[-T]
class B[-T] extends A[A[T]]
我得到以下错误:

error: contravariant type T occurs in covariant position in type [-T]A[A[T]]{def <init>(): B[T]} of class B
错误:逆变型T出现在类B的类型[-T]A[A[T]{def():B[T]}的协变位置
为什么这是一个错误?

是编译器定义的
A
(或
B
)的构造函数

代码的问题是
B[-T]扩展了A[A[T]
导致了矛盾

举个例子:

class A[-T]
class B[-T] extends A[A[T]]

class Animal
class Cat extends Animal

简而言之,让我们使用
A这是一个错误,因为
A[A[T]]
在类型T中是协变的

协变类型的定义来自:

在编程语言的类型系统中,键入规则或 类型构造函数为:

  • 协变的,如果它保持类型的顺序(≤), 从更具体到更一般的订单类型
  • 相反的,如果它颠倒了这个顺序
考虑以下几点:

class Fruit
class Banana extends Fruit

但以下情况将导致错误:

scala> type AA[-T] = A[A[T]]
<console>:15: error: contravariant type T occurs in covariant position in type [-T]A[A[T]] of type AA
       type AA[-T] = A[A[T]]
            ^

scala> type AAA[+T] = A[A[A[T]]]
<console>:15: error: covariant type T occurs in contravariant position in type [+T]A[A[A[T]]] of type AAA
       type AAA[+T] = A[A[A[T]]]
            ^
在这种情况下,我们得到:

B[Fruit] <: B[Banana] <: A[A[Banana]] 

现在我们有一个
bananas2
类型
a[a[Banana]]
的值,它指向一个
a[a[Fruit]
的实例,它违反了类型安全,因为
a[a[Banana]]
是构造函数,并且是隐式定义的。那么为什么我可以定义
类B[-T]
?方法
init
也会存在,并返回我a
B[T]
,它编译得很好。B[Cat]=a[a[Cat]]不是真的。不过,你最多也有B[Cat]是。a
B[Cat]
是a
a[Cat]
就像
列表[a]
也是a
Seq[a]
Int
AnyVal
。如果类扩展了某个对象,那么它就是该对象。上界并不严格。事实上,a
B[Cat]
是a
a[Cat]]
不是平等的,因为我们谈论的是类型。你的最终含义依赖于错误的假设,即如果
A那么你是对的,我不能定义
类型AA[-T]=A[A[T]
。但是对于我最初的问题,定义一个扩展
A[A[T]]的类怎么样
但将
T
定义为逆变参数?@MikaëlMayer I更新了答案以涵盖原始问题。请看一看。
B[Animal] <: B[Cat] => A[A[Animal]] <: A[A[Cat]]
class Fruit
class Banana extends Fruit
Banana <: Fruit
A[Banana] :> A[Fruit] // Because A is contravariant in type T
A[A[Banana]] <: A[A[Fruit]] // Again because A is contravariant in type T
scala> type AA[+T] = A[A[T]]
defined type alias AA

scala> type AAA[-T] = A[A[A[T]]]
defined type alias AAA
scala> type AA[-T] = A[A[T]]
<console>:15: error: contravariant type T occurs in covariant position in type [-T]A[A[T]] of type AA
       type AA[-T] = A[A[T]]
            ^

scala> type AAA[+T] = A[A[A[T]]]
<console>:15: error: covariant type T occurs in contravariant position in type [+T]A[A[A[T]]] of type AAA
       type AAA[+T] = A[A[A[T]]]
            ^
class B[-T] extends A[A[T]]
B[Fruit] <: B[Banana] <: A[A[Banana]] 
val fruits: B[Fruit] = new B[Fruit]
val bananas1: B[Banana] = fruits
val bananas2: A[A[Banana]] = bananas1