Pregunta

@uncheckedVariance se puede utilizar para cerrar la brecha entre las anotaciones de varianza sitio de la declaración de Scala y genéricos invariantes de 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

Esto dice que java.util.Comparator es naturalmente contra-variante, que es el parámetro de tipo T aparece en parámetros y nunca en un tipo de retorno.

Esto plantea la pregunta: ¿por qué se utilizó también en la biblioteca de colecciones Scala que no se extiende desde interfaces Java

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

¿Cuáles son los usos válidos para esta anotación?

¿Fue útil?

Solución

El problema es que se utiliza GenericTraversableTemplate dos veces: una vez para colecciones mutables (donde su parámetro de tipo debe ser invariante), y una vez para colecciones inmutables (donde covarianza es invariablemente rey)

.

typechecks de GenericTraversableTemplate asumir cualquiera de covarianza o invariancia para el parámetro de un tipo. Sin embargo, cuando heredamos en un rasgo mutable, tenemos que elegir invariancia. Por el contrario, nos gustaría covarianza en una subclase inmutable.

Dado que no podemos abstracta sobre la anotación varianza (todavía ;-)) en GenericTraversableTemplate, por lo que podríamos haber una instancia que a cualquiera de ellos dependiendo de la subclase, tenemos que recurrir a la fundición (@uncheckVariance es esencialmente una especie -emitir). Para leer más, recomiendo mi tesis (lo siento ;-)) o nuestro reciente papel bitrot

Otros consejos

En mi tesis describo un cálculo, Scalina, que tiene límites y anotaciones de varianza como parte del lenguaje de clase (una versión anterior también está disponible como un taller papel ). La relevancia de esta discusión es el siguiente paso que quiero tomar en el desarrollo de este cálculo: construir otra capa por encima de eso, para que pueda abstracta sobre los límites (Fácil) y anotaciones de varianza (hace girar mi cabeza). En realidad, usted no sólo tachuela 1 capa extra de allí, sino generalizar sus construcciones polimorfismo por lo que trabajar en todos los niveles, y hacer sus "atributos" (cotas, anotaciones de varianza, argumentos implícitos necesarios, ...) en tipos regulares con tipos especiales, que son todos sujetos a la abstracción.

Los atributos son "tipos" idea se explica muy bien por Edsko de Vries en el contexto de tipos de singularidad.

  

Singularidad Typing simplificado ,   Edsko de Vries, Rinus Plasmeijer, y David Abrahamson.   En Olaf Chitil, Zoltán Horváth y Viktória Zsók (Eds.):   IFL 2007, LNCS 5083, pp. 201-218, 2008.

     

Resumen: Se presenta un tipo de singularidad   sistema que es más simple que tanto   sistema de la singularidad de limpia y el   sistema que propusimos anteriormente. El nuevo   Tipo de sistema es sencillo   implementar y añadir a la ya existente   compiladores, y fácilmente se pueden ampliar   con características avanzadas tales como mayor   tipos de rango y impredicativity. Nosotros   describir nuestra aplicación en Morrow,   un lenguaje funcional experimental   con estas dos características. Finalmente nosotros   demostrar solidez del tipo de núcleo   sistema con respecto a la   Call-by-necesidad cálculo lambda.

he encontrado otra vez, cuando se utilice @uncheckedVariance - el método sintético que devuelve el valor predeterminado para un parámetro de un tipo abstracto:

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();
          ()
        }
      }
    }
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top