Set
ist als Set[A]
definiert. Es benötigt einen in-variant Parameter. Das folgende Vorgehen funktioniert wie erwartet, da wir das Co-Varianten-Argument übergeben:
Aber das Folgende funktioniert:
%Vor% Oben, wie ich es sehe, konvertiert der Scala-Compiler Set("hi")
in Set[Object]
type und funktioniert daher.
Was macht die Typinferenz hier? Kann jemand bitte eine Verbindung zur Spezifikation herstellen, die das Verhalten erklärt und wann passiert es im Allgemeinen? Sollte es in solchen Fällen nicht zu einem Kompilierfehler kommen? Als 2 verschiedene Ausgaben für denselben Operationstyp.
Nicht sicher, aber ich denke, was Sie suchen, ist in der Sprache beschrieben Spezifikation unter "Lokale Inferenz" (zu diesem Zeitpunkt, Abschnitt 6.26.4 auf Seite 100).
Die lokale Inferenz leitet Typargumente ab, die an Ausdrücke des polymorphen Typs übergeben werden. Sagen wir, dass e vom Typ [a 1 <: l <1> ist: <1> ..., a n <: Ln <: n
von Typen T i zu finden > so dass
und keine explizite Art Parameter werden angegeben.
Lokale Inferenz konvertiert diesen Ausdruck in eine Typanwendung e [T 1, ..., T n . Die Auswahl der Typargumente T <1>, ..., T n hängt vom Kontext ab, in dem der Ausdruck auftritt, und vom erwarteten Typ pt . Es gibt drei Fälle.
[...]
Wenn der Ausdruck e als Wert angezeigt wird, ohne dass er auf Wertargumente angewendet wird, werden die Typargumente abgeleitet, indem ein Beschränkungssystem aufgelöst wird, das den Typ des Ausdrucks T mit dem verknüpft erwarteter Typ pt . Ohne Beschränkung der Allgemeinheit können wir annehmen, dass T ein Werttyp ist; Wenn es sich um einen Methodentyp handelt, wenden wir eta-expansion an, um es in einen Funktionstyp zu konvertieren. Lösung bedeutet, für die Typparameter a i σ
Keiner der abgeleiteten Typen T i ist ein Singletontyp
Alle Typparametergrenzen werden respektiert, dh σ L i & lt;: a i und σ a i & lt ;: U U i für i = 1, ..., n .
Der Typ des Ausdrucks entspricht dem erwarteten Typ, d. h. σ T & lt; σ pt .
Es ist ein Kompilierzeitfehler, wenn keine solche Ersetzung existiert. Wenn mehrere Substitutionen vorhanden sind, wählt die lokale Inferenz für jede Typvariable a i einen minimalen oder maximalen Typ T < em> des Lösungsraums. Ein maximaler Typ T i wird gewählt, wenn der Typparameter a i widersprüchlich im Typ erscheint T des Ausdrucks. Ein minimaler Typ T i wird in allen anderen Situationen gewählt, dh wenn die Variable im Typ T kovariant, nichtvariabel oder gar nicht auftritt . Wir nennen eine solche Substitution eine optimale Lösung des gegebenen Beschränkungssystems für den Typ T .
Kurz gesagt: Scalac muss Werte für die generischen Typen auswählen, die Sie weggelassen haben, und wählt die spezifischsten möglichen Optionen unter der Bedingung aus, dass das Ergebnis kompiliert wird.
Der Ausdruck Set("hi")
kann entweder ein scala.collection.immutable.Set[String]
oder ein scala.collection.immutable.Set[Object]
sein, je nachdem, was der Kontext erfordert. (A String
ist natürlich ein gültiges Object
.) Wenn Sie dies schreiben:
Der Kontext erfordert Set[Object]
, also der Typ, der abgeleitet wird; aber wenn du das schreibst:
Der Kontext wird nicht angegeben, daher wird der spezifischere Typ Set[String]
ausgewählt, was (wie erwartet) dazu führt, dass a & b
falsch eingegeben wird.