EDIT : réécrit cette question en fonction de la réponse originale
La scala.collection.immutable.Set
classe n'est pas covariante dans son paramètre de type. Pourquoi est-ce?
import scala.collection.immutable._
def foo(s: Set[CharSequence]): Unit = {
println(s)
}
def bar(): Unit = {
val s: Set[String] = Set("Hello", "World");
foo(s); //DOES NOT COMPILE, regardless of whether type is declared
//explicitly in the val s declaration
}
scala
set
covariance
scala-collections
oxbow_lakes
la source
la source
foo(s.toSet[CharSequence])
compile bien. LatoSet
méthode est O (1) - elle s'enroule simplementasInstanceOf
.foo(Set("Hello", "World"))
compile aussi sur 2.10, puisque Scala semble être capable de déduire le bon type de Set. Cela ne fonctionne pas avec les conversions implicites ( stackoverflow.com/questions/23274033/… ).Réponses:
Set
est invariant dans son paramètre de type en raison du concept derrière les ensembles en tant que fonctions. Les signatures suivantes devraient clarifier légèrement les choses:Si
Set
étaient covariantes dansA
, laapply
méthode serait incapable de prendre un paramètre de type enA
raison de la contravariance des fonctions.Set
pourraient être contravariant dansA
, mais cela provoque aussi des problèmes lorsque vous voulez faire des choses comme ceci:En bref, la meilleure solution est de garder les choses invariantes, même pour la structure de données immuable. Vous remarquerez que
immutable.Map
c'est également invariant dans l'un de ses paramètres de type.la source
List(1,2,3).contains _
est(Any) => Boolean
, tandis que le type deSet(1,2,3).contains _
estres1: (Int) => Boolean
.à http://www.scala-lang.org/node/9764 Martin Odersky écrit:
Donc, il semble que tous nos efforts pour construire une raison de principe à cela ont été malavisés :-)
la source
Seq
covariantes ... est-ce que je manque quelque chose?Array[Any]
interne.EDIT : pour quiconque se demande pourquoi cette réponse semble légèrement hors sujet, c'est parce que je (l'interlocuteur) ai modifié la question.
L'inférence de type de Scala est assez bonne pour comprendre que vous voulez des CharSequences et non des Strings dans certaines situations. En particulier, ce qui suit fonctionne pour moi dans 2.7.3:
Quant à savoir comment créer des immuables.HashSets directement: ne le faites pas. En tant qu'optimisation de l'implémentation, immutable.HashSets de moins de 5 éléments ne sont pas en fait des instances d'immutable.HashSet. Ils sont soit EmptySet, Set1, Set2, Set3 ou Set4. Ces classes sous-classe immutable.Set, mais pas immutable.HashSet.
la source