Domanda

@uncheckedVariance può essere utilizzato per colmare il divario tra sito dichiarazione annotazioni di varianza di Scala e generici invarianti di 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

Questo dice che java.util.Comparator è naturalmente contra-variante, che è il parametro di tipo T appare nei parametri e mai in un tipo di ritorno.

Questo pone la domanda: perché si usa anche nella biblioteca collezioni Scala che non si estende da interfacce Java

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

Quali sono gli usi validi per questa annotazione?

È stato utile?

Soluzione

Il problema è che GenericTraversableTemplate viene utilizzato due volte: una volta per le collezioni mutabili (dove il suo parametro di tipo dovrebbe essere invariante), e una volta per le collezioni immutabili (dove covarianza è invariabilmente re)

.

typechecks di GenericTraversableTemplate assumendo sia covarianza o invarianza del parametro Un tipo. Tuttavia, quando abbiamo ereditato in un tratto mutevole, dobbiamo raccogliere invarianza. Al contrario, ci piacerebbe covarianza in una sottoclasse immutabile.

Poiché non possiamo astratta sull'annotazione varianza (ancora ;-)) in GenericTraversableTemplate, così che abbiamo potuto istanziata ad uno dei due a seconda della sottoclasse, dobbiamo ricorrere a getto (@uncheckVariance è essenzialmente una sorta -cast). Per ulteriori approfondimenti, vi consiglio la mia tesi di laurea (scusate ;-)) o il nostro recente carta bitrot

Altri suggerimenti

Nella mia tesi ho descritto un calcolo, Scalina, che ha limiti e le annotazioni di varianza come parte del linguaggio genere (una versione precedente è disponibile anche come carta officina ). La rilevanza di questa discussione è il prossimo passo che voglio prendere nello sviluppo di questo calcolo: costruire un altro strato in cima a quello in modo che possiate astratto su limiti (facile) e le annotazioni di varianza (mi fa girare la testa). In realtà, si sarebbe non solo virata 1 strato supplementare in là, ma piuttosto allargare la costrutti polimorfismo in modo da lavorare a tutti i livelli, e rendere il vostro "attributi" (limiti, annotazioni di varianza, argomenti impliciti richiesti, ...) in tipi regolari con i generi speciali, che sono tutti soggetti all'astrazione.

Gli "attributi sono tipi" idea è spiegato bene dal Edsko de Vries nel contesto dei tipi di unicità.

  

Unicità Digitando semplificato ,   Edsko de Vries, Rinus Plasmeijer, e David Abrahamson.   In Olaf Chitil, Zoltán Horváth e Viktória Zsók (Eds.):   IFL 2007 LNCS 5083, pp. 201-218, 2008.

     

Premessa: Vi presentiamo un tipo di unicità   sistema che è più semplice che sia   sistema di unicità è pulito e il   Sistema abbiamo proposto in precedenza. Il nuovo   Sistema tipo è semplice da   implementare e aggiungere al già esistente   compilatori, e possono facilmente essere estese   con funzioni avanzate come più alti   Tipi di rango e impredicativity. Noi   descrivere la nostra implementazione in Morrow,   un linguaggio funzionale sperimentale   con entrambe queste caratteristiche. Infine,   dimostrare solidità del tipo nucleo   sistema rispetto al   Call-by-necessità lambda calcolo.

Ho trovato un altro momento in cui viene utilizzato @uncheckedVariance - il metodo di sintesi che restituisce il valore predefinito per un parametro di un tipo astratto:

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();
          ()
        }
      }
    }
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top