Scala中需要@uncheckedvariance何时,为什么在generictraversabletemplate中使用它?
-
20-09-2019 - |
题
@uncheckedVariance
可用于弥合Scala声明站点差异注释和Java不变的仿制药之间的差距。
scala> import java.util.Comparator
import java.util.Comparator
scala> trait Foo[T] extends Comparator[T]
defined trait Foo
scala> trait Foo[-T] extends Comparator[T]
<console>:5: error: contravariant type T occurs in invariant position in type [-T]java.lang.Object with java.util.Comparator[T] of trait Foo
trait Foo[-T] extends Comparator[T]
^
scala> import annotation.unchecked._
import annotation.unchecked._
scala> trait Foo[-T] extends Comparator[T @uncheckedVariance]
defined trait Foo
这说明java.util.comparator自然是矛盾的,那是类型参数 T
出现在参数中,从未出现在返回类型中。
这就提出了一个问题:为什么它也不从Java接口延伸的Scala Collections库中使用?
trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance]
此注释的有效用途是什么?
解决方案
问题在于,使用了两次通用versababletemplate:一次用于可变的集合(其类型参数应该是不变的),并且一次用于不可变的集合(其中协方差始终是不变性的国王)。
generictraversabletemplate的Typechecks假设A类型参数的协方差或不变性。但是,当我们以可变特征继承它时,我们必须选择不变性。相反,我们希望在不可变的子类中协方差。
由于我们无法在generictraversabletemplate中的差异注释(;-))中抽象,因此我们可以根据子类实例化将其实例化,因此我们必须求助于铸造(@uncheckeckvariance本质上是一种基本上是一种式铸造) 。要进一步阅读,我建议我的论文(对不起;-)或我们最近的 比特罗特纸
其他提示
在我的论文中,我描述了一个微积分Scalina,它具有界限和差异注释作为类型语言的一部分(也可以作为一个早期版本作为一个 车间纸)。与此讨论的相关性是我要开发这种演算时要采取的下一步:在此基础上构建另一层,以便您可以在界限(简单)和差异注释(使我的头旋转)上抽象。实际上,您不仅会在那里添加1个额外的一层,还可以将您的多态性结构概括为各个级别,并使您的“属性”(界限,差异注释,需要隐性参数,...)为常规类型。具有特殊种类,所有这些都可以抽象。
在唯一性类型的背景下,Edsko de Vries很好地解释了“属性是类型”的想法。
独特性键入简化, ,Edsko de Vries,Rinus Plasmeijer和David Abrahamson。在Olaf Chitil,ZoltánHorváth和ViktóriaZsók(编辑):IFL 2007,LNCS 5083,第201-218页,2008年。
摘要:我们提出了一个唯一类型的系统,它比清洁的独特系统和我们先前提出的系统更简单。新型类型系统可以简单地实现并添加到现有编译器中,并且可以轻松扩展使用高级类型和不可思议的高级功能。我们在Morrow中描述了我们的实现,这是一种具有这两种功能的实验功能语言。最后,我们证明了核心类型系统相对于逐个呼叫的lambda演算的声音。
我发现了另一个使用@uncheckedVariance的时间 - 返回抽象类型参数的默认值的合成方法:
M:\>scala -Xprint:typer -e "class C { def p[T >: Null](t: T = null) = t }"
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
final object Main extends java.lang.Object with ScalaObject {
def this(): object Main = {
Main.super.this();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
class C extends java.lang.Object with ScalaObject {
<synthetic> def p$default$1[T >: Null <: Any]: Null @scala.annotation.unchecked.uncheckedVariance = null;
def this(): this.C = {
C.super.this();
()
};
def p[T >: Null <: Any](t: T = null): T = t
}
};
{
new $anon();
()
}
}
}
}