本文解释了Scala 3代码中的每个泛型类型参数都被视为依赖类型,以符合DOT逻辑:
https://dotty.epfl.ch/docs/internals/higher-kinded-v2.html
即:
二重性核心思想:参数化类,如
类Map[K,V]
被视为等效于具有类型成员的类型:
类Map{类型Map$K;键入Map$V}
(the文章可能已过时,但设计理念仍应保持不变)
因此,我希望类型参数的任何逆变和协变修饰符也被重写,所以我做了一个快速的实验,编译器应该能够转换以下代码:
object AsArg {
trait P[+TT] {
val vv: TT
}
trait P1 extends P[Product] {
val vv: Product
}
trait P2 extends P1 with P[Tuple1[Int]] {
val vv: Tuple1[Int]
}
}
变成这样:
object AsDependentType {
trait P {
type TT
val vv: TT
}
trait P1 extends P {
type TT <: Product
val vv: Product
}
trait P2 extends P1 with P {
type TT <: Tuple1[Int]
val vv: Tuple1[Int]
}
}
具有讽刺意味的是,转换后,编译器抛出以下错误:
[Error] ...CovariantDependentType.scala:30:11: error overriding value vv in trait P of type P1.this.TT;
value vv of type Product has incompatible type
[Error] ...CovariantDependentType.scala:36:11: error overriding value vv in trait P of type P2.this.TT;
value vv of type Tuple1[Int] has incompatible type
two errors found
那么转换后正确的等价代码是什么呢?
1条答案
按热度按时间8wtpewkr1#
In/co/contra-variance是类型构造函数
F[T]
的一个属性。F
是协变的,如果对于所有A <: B
,F[A] <: F[B]
,F
是反变的,如果对于所有A <: B
,F[B] <: F[A]
,F
是不变的,如果对于所有A <: B
,F[A]
和F[B]
是<:
不相关的。类型参数和类型成员在Scala 2和Scala 3中是不同的东西。
对于类型参数,可以在申报地点设置差异
或在调用位置
在Java中没有
+
/-
,所以类型参数的变量必须总是在调用点设置为? extends ...
、? super ...
。对于Scala中的类型成员,也没有
+
/-
,因此必须在调用点设置方差类型参数代码
可以在Scala 2中转换为类型成员代码,如下所示
由于
TT1 forSome {type TT1 >: TT} =:= Any
,它等于由于存在类型在Scala 3中被推荐为路径依赖类型,因此在Scala 3中可以被翻译为(*)或