Когда @UncheckedVariance необходимо в Scala, и почему она используется в GenericTraversableTemplate?

StackOverflow https://stackoverflow.com/questions/2454281

Вопрос

@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 появляется в параметрах и никогда не в типе возврата.

Возникает вопрос: почему он также используется в библиотеке коллекций Scala, которая не простирается от интерфейсов Java?

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

Каковы действительные использования для этой аннотации?

Это было полезно?

Решение

Проблема заключается в том, что GenericTraversableTemplate используется дважды: один раз для изменяющихся коллекций (где его параметр типа должен быть инвариантным), и один раз для неизменных коллекций (где ковариация неизменно является королем).

Generictraversabletetemplate typechecks, предполагающие либо ковариацию, либо инвариантность для параметра типа A. Однако, когда мы наследуем это в изменчивой черте, мы должны выбрать инвариантность. И наоборот, мы хотели бы ковариации в неизменном подклассе.

Поскольку мы не можем абстрагировать аннотацию дисперсии (пока ;-)) в generictraversabletemplate, чтобы мы могли создать его для любого человека в зависимости от подкласса, мы должны прибегнуть к кастингу (@uncheckvariance-это, по сути, добрый) Анкет Для дальнейшего чтения я рекомендую свою диссертацию (извините ;-)) или наш недавний биттрот бумага

Другие советы

В своем тезисе я описываю исчисление, Scalina, которое имеет границы и аннотации дисперсии как часть вида (более ранняя версия также доступна как мастерская бумага) Актуальность к этому обсуждению является следующим шагом, который я хочу сделать при разработке этого исчисления: построить еще один слой, чтобы вы могли абстрагировать границы (легкие) и аннотации дисперсии (заставляет мою голову вращаться). На самом деле, вы бы не просто прикрепили бы 1 дополнительный слой, а скорее обобщение своих полиморфизма, чтобы они работали на всех уровнях и превращали ваши «атрибуты» (границы, аннотации дисперсии, требуемые неявные аргументы, ...) в обычные типы с особыми видами, которые подчиняются абстракции.

Идея «атрибуты - это типы», которую хорошо объясняется Эдско -де -Врисом в контексте типов уникальности.

Уникальность ввода, упрощенная, Эдско де Врис, Ринус Пласмийер и Дэвид Абрахамсон. В Olaf Chitil, Zoltán Horváth и Viktória Zsók (Eds.): IFL 2007, LNCS 5083, с. 201-218, 2008.

Аннотация: Мы представляем систему типа уникальности, которая проще, чем система уникальности Clean и предлагаемой нами системы. Новая система типа проста для реализации и добавления к существующим компиляторам, и ее можно легко расширить с помощью расширенных функций, таких как типы более высоких рангов и впечатляют. Мы описываем нашу реализацию в 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();
          ()
        }
      }
    }
  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top