代码之家  ›  专栏  ›  技术社区  ›  retronym

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

  •  38
  • retronym  · 技术社区  · 16 年前

    @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
    

    T

    这就提出了一个问题:为什么Scala集合库中也使用了它,它不从Java接口扩展?

    trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance]
    

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

    3 回复  |  直到 6 年前
        1
  •  29
  •   Adriaan Moors    16 年前

    问题是GenericTraversableTemplate使用了两次:一次用于可变集合(其类型参数应该是不变的),一次用于不可变集合(协方差总是最大的)。

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

    因为我们不能抽象出方差注释(但是;-)在GenericTraversableTemplate中,为了使我们能够根据子类将其实例化为任何一个,我们必须求助于强制转换(@uncheckVariance本质上是一种强制转换)。为了进一步阅读,我推荐我的论文(对不起;-)或者我们最近 bitrot paper

        2
  •  8
  •   Community Mohan Dere    5 年前

    在我的论文中,我描述了一个有界的微积分Scalina;作为种类语言的一部分的差异注释(早期版本也可以作为 workshop paper ). 与此讨论相关的是我在开发此演算时要采取的下一步:在此基础上构建另一层,以便可以抽象出越界(简单)和方差注释(使我头晕目眩)。实际上,你不只是在上面多加一层,而是泛化你的多态结构,让它们在所有层次上都能工作,并把你的“属性”(边界、方差注释、所需的隐式参数等等)变成具有特殊类型的正则类型,这些类型都要经过抽象。

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

    Uniqueness Typing Simplified 埃德斯科·德·弗里斯、里努斯·普拉斯梅耶尔和大卫·亚伯拉罕。 在Olaf Chitil、Zoltn Horvth和Viktria Zsk(编辑): IFL 2007,LNCS 5083,第201-2182008页。

    摘要:我们提出了一种唯一性类型 比两者都简单的系统 我们之前提出的系统。新的 类型系统很容易 实施并添加到现有 具有高级功能,如 等级类型和不确定度。我们 描述我们明天的实施情况, 实验函数语言

        3
  •  5
  •   retronym    16 年前

    我发现了另一个使用@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();
              ()
            }
          }
        }
      }