2010-03-16 11 views
32

@uncheckedVariance kann verwendet werden, um die Lücke zwischen Scala Deklaration Site Varianz Annotationen und Javas invarianten Generics zu überbrücken. und nie in einem RückgabetypWann wird @uncheckedVariance in Scala benötigt und warum wird es in GenericTraversableTemplate verwendet?

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 

Dies sagt, dass java.util.Comparator natürlich kontravarianten ist, das ist der Typ-Parameter T in Parametern angezeigt.

Dies wirft die Frage auf: warum wird es auch in der Scala Collections-Bibliothek verwendet, die nicht von Java-Schnittstellen ausgeht?

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

Was sind die gültigen Verwendungen für diese Annotation?

+0

Gute Frage! –

Antwort

25

Das Problem ist, dass GenericTraversableTemplate zweimal verwendet wird: einmal für veränderbare Auflistungen (wobei sein Typparameter invariant sein sollte) und einmal für unveränderbare Auflistungen (wobei Kovarianz immer König ist).

GenericTraversableTemplate-Typchecks, die für den Parameter A-Typ entweder Kovarianz oder Invarianz annehmen. Wenn wir es jedoch in einer veränderlichen Eigenschaft erben, müssen wir die Invarianz auswählen. Umgekehrt möchten wir die Kovarianz in einer unveränderlichen Unterklasse.

Da wir in GenericTraversableTemplate nicht über die Varianz Annotation (noch ;-)) abstrahieren können, so dass wir sie abhängig von der Unterklasse zu einer Instanz hätten machen können, müssen wir auf Casting zurückgreifen (@uncheckVariance ist im Wesentlichen ein Art-Cast). Für weitere Lektüre empfehle ich meine Dissertation (sorry ;-)) oder unser letzte bitrot paper

+0

Danke! Ich habe letzte Woche das Bitrot-Papier gelesen, aber es geht nicht speziell um das Problem der Integration von Co- und In-Variante-Sammlungen unter einem gemeinsamen Elternteil. Ich denke, ich werde sehen, was in Ihrer Dissertation ist :) – retronym

+0

Nun, es war vor allem eine schamlose Stecker - meine Dissertation befasst sich nicht direkt mit genau diesem Problem. Es sollte jedoch mehr Überlegungen zu dieser stärkeren Polymorphie anstellen. Ich füge unten noch einige Gedanken hinzu. –

+0

"ausnahmslos König" ... ha ha –

8

In meiner Arbeit ich ein Kalkül beschreiben, Scalina, die auch Grenzen & Varianz Anmerkungen im Rahmen der Art Sprache (eine frühere Version ist, hat erhältlich als workshop paper). Die Relevanz für diese Diskussion ist der nächste Schritt, den ich bei der Entwicklung dieses Kalküls nehmen möchte: Erstelle eine weitere Ebene darüber, so dass du Grenzen (einfach) und Varianzanmerkungen abstrahieren kannst (macht meinen Kopf rotieren). Eigentlich würden Sie nicht nur eine zusätzliche Ebene anhängen, sondern Ihre Polymorphismus-Konstrukte verallgemeinern, so dass sie auf allen Ebenen funktionieren und Ihre "Attribute" (Grenzen, Varianz-Annotationen, erforderliche implizite Argumente, ...) zu regulären Typen machen mit speziellen Arten, die alle der Abstraktion unterliegen.

Die Idee "Attribute sind Typen" wird von Edsko de Vries im Zusammenhang mit Eindeutigkeitstypen gut erklärt.

Uniqueness Typing Simplified, Edsko de Vries, Rinus Plasmeijer und David Abrahamson. In Olaf Chitil, Zoltán Horváth und Viktória Zsók (Hrsg.):. IFL 2007 LNCS 5083, Seiten 201-218, 2008.

Abstract: Wir präsentieren eine Art System Einzigartigkeit, die einfacher als die beiden reinigen ist, ist Eindeutigkeitssystem und das System, das wir vorher vorgeschlagen haben. Das neue Typ System ist einfach zu zu implementieren und zu bestehenden Compiler hinzufügen, und kann leicht erweitert werden mit erweiterten Funktionen wie höhere Rangarten und Imprägniertheit. Wir beschreiben unsere Implementierung in Morrow, eine experimentelle funktionale Sprache mit diesen beiden Funktionen.Schließlich beweisen wir Solidität des Kerntyps System in Bezug auf die Call-by-Need-Lambda-Kalkül.

5

ich ein anderes Mal gefunden, wo @uncheckedVariance verwendet wird - die synthetische Methode, die den Standardwert für einen Parameter eines abstrakten Typs zurückgibt:

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(); 
     () 
     } 
     } 
    } 
    } 
Verwandte Themen