Scala何时需要@uncheckedVariance,为什么在GenericTraversableTemplate中使用它?

Scala何时需要@uncheckedVariance,为什么在GenericTraversableTemplate中使用它?,scala,scala-2.8,annotations,unchecked,variance,Scala,Scala 2.8,Annotations,Unchecked,Variance,@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&

@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

此注释的有效用途是什么?

问题是GenericTraversableTemplate使用了两次:一次用于可变集合(其类型参数应为不变),一次用于不可变集合(协方差始终为最大值)

GenericTraversableTemplate的类型检查假定类型参数的协方差或不变性。然而,当我们以可变特征继承它时,我们必须选择不变性。相反,我们想要一个不可变的子类中的协方差


由于我们无法抽象GenericTraversableTemplate中的方差注释(但;-),因此我们可以根据子类将其实例化为任意一个,因此我们必须求助于强制转换(@uncheckVariance本质上是一种强制转换)。为了进一步阅读,我推荐我的论文(抱歉;-))或我们最近的

在我的论文中,我描述了一个微积分,Scalina,它有边界和方差注释作为种类语言的一部分(早期版本也可以作为。与此讨论相关的是我在开发此演算时要采取的下一步:在其上构建另一层,以便您可以抽象超边界(简单)和方差注释(使我头晕目眩)。事实上,你不应该在上面多加一层,而应该概括你的多态性结构,让它们在所有层次上都能工作,并将你的“属性”(边界、方差注释、必需的隐式参数等)转换成具有特殊类型的常规类型,这些类型都需要抽象

Edsko de Vries在惟一性类型的上下文中很好地解释了“属性就是类型”的思想

,, 埃德斯科·德弗里斯、里努斯·普拉斯梅杰和大卫·亚伯拉罕·森。 在Olaf Chitil,Zoltán Horváth和Viktória Zsók(编辑): IFL 2007,LNCS 5083,第201-218页,2008年

摘要:我们提出了一种唯一性类型 比两者都简单的系统 Clean的独特性系统和 我们先前提出的系统。新的 类型系统很容易实现 实现并添加到现有的 编译器,并且可以轻松地进行扩展 具有高级功能,如更高的 等级类型和不确定性。我们 请描述我们明天的实施情况, 实验函数语言 具有这两个特性。最后,我们 证明核心类型的可靠性 关于 按需调用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();
          ()
        }
      }
    }
  }
M:\>scala-Xprint:typer-e“class C{defp[T>:Null](T:T=Null)=T}”
[[typer末尾的语法树]]//Scala源:(虚拟文件)
包装{
final object Main使用ScalaObject扩展了java.lang.object{
def this():对象主={
Main.super.this();
()
};
def main(argv:Array[String]):单位={
val args:Array[String]=argv;
{
最后一个类$anon扩展了scala.AnyRef{
def this():匿名类$anon={
$anon.super.this();
()
};
类C使用ScalaObject扩展java.lang.Object{

def p$默认值$1[T>:Null:Null谢谢!我很喜欢上周读的bitrot论文,但它并没有专门讨论在一个共同的父项下集成co和in变体集合的问题。我想我会看看你的论文中的内容:)嗯,这基本上是一个无耻的插件——我的论文并没有直接处理这个确切的问题。我不过,t应该对这种更强大的多态性有更多的思考。我将在下面补充一些想法。“永远是国王”…哈哈
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();
          ()
        }
      }
    }
  }