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]
이 주석에 대한 유효한 용도는 무엇입니까?
해결책
문제는 GenericTraversableTemplate이 두 번 사용된다는 것입니다. 한 번은 Mutable Collections (유형 매개 변수가 변하지 않아야 함), 불변의 컬렉션의 경우 (공분산이 항상 왕이되는 곳).
GenericTraversableTemplate의 TypeChecks는 A 형 매개 변수에 대한 공분산 또는 불변성을 가정합니다. 그러나 돌연변이 형 특성으로 물려 받으면 불변을 선택해야합니다. 반대로, 우리는 불변의 서브 클래스에서 공분산을 원합니다.
GenericTraversableTemplate에서 분산 주석 (아직 ;-))에 대해 추상화 할 수 없으므로 서브 클래스에 따라 하나로 인스턴스화 할 수 있으므로 캐스팅에 의지해야합니다 (@uncheckVariance는 본질적으로 친절한 캐스트입니다). . 추가로 읽으려면 논문 (죄송합니다 ;-)) 또는 최근 비트 롯지 용지
다른 팁
내 논문에서 나는 친절한 언어의 일부로 경계 및 분산 주석이있는 미적분학 Scalina를 설명합니다 (이전 버전은 또한 워크샵 종이). 이 토론과의 관련성은이 미적분학을 개발하기 위해 취하고 싶은 다음 단계입니다. 그 위에 다른 레이어를 구축하여 바운드 (쉬운)와 분산 주석 (내 머리를 돌리게 함)을 추상화 할 수 있습니다. 실제로, 당신은 거기에 1 개의 추가 레이어를 충족시키는 것이 아니라 다형성 구성을 일반화하여 모든 수준에서 작동하고 "속성, 분산 주석, 필요한 암시 적 인수 등을 일반 유형으로 만듭니다. 특수한 종류의 경우 모두 추상화의 대상이됩니다.
"속성은 유형"아이디어는 독창성 유형의 맥락에서 Edsko de Vries에 의해 멋지게 설명됩니다.
독창성 입력 단순화, Edsko de Vries, Rinus Plasmeijer 및 David Abrahamson. Olaf Chitil, Zoltán Horváth 및 Viktória Zsók (Eds.) : IFL 2007, LNCS 5083, pp. 201-218, 2008.
초록 : 우리는 Clean의 독창성 시스템과 이전에 제안한 시스템보다 간단한 독창성 유형 시스템을 제시합니다. 새로운 유형 시스템은 기존 컴파일러를 구현하고 추가하기가 간단하며 높은 순위 유형 및 임계 성과 같은 고급 기능으로 쉽게 확장 할 수 있습니다. 우리는이 두 가지 기능을 갖춘 실험적인 기능 언어 인 Morrow에서 구현을 설명합니다. 마지막으로, 우리는 콜으로 필요한 람다 미적분과 관련하여 핵심 유형 시스템의 건전성을 증명합니다.
@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();
()
}
}
}
}