EDITAR : reescribió esta pregunta según la respuesta original
La scala.collection.immutable.Set
clase no es covariante en su parámetro de tipo. ¿Por qué es esto?
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
fuente
fuente
foo(s.toSet[CharSequence])
compila bien. EltoSet
método es O (1), simplemente envuelveasInstanceOf
.foo(Set("Hello", "World"))
compila en 2.10, ya que Scala parece ser capaz de inferir el tipo correcto de Set. Sin embargo, no funciona con conversiones implícitas ( stackoverflow.com/questions/23274033/… ).Respuestas:
Set
es invariante en su parámetro de tipo debido al concepto detrás de los conjuntos como funciones. Las siguientes firmas deberían aclarar un poco las cosas:Si
Set
fuera covarianteA
, elapply
método no podría tomar un parámetro de tipoA
debido a la contravarianza de funciones.Set
potencialmente podría ser contravariant enA
, pero esto también provoca problemas cuando se quiere hacer cosas como esta:En resumen, la mejor solución es mantener las cosas invariables, incluso para la estructura de datos inmutable. Observará que
immutable.Map
también es invariante en uno de sus parámetros de tipo.fuente
List(1,2,3).contains _
es(Any) => Boolean
, mientras que el tipo deSet(1,2,3).contains _
esres1: (Int) => Boolean
.en http://www.scala-lang.org/node/9764 Martin Odersky escribe:
Entonces, parece que todos nuestros esfuerzos para construir una razón de principios para esto fueron equivocados :-)
fuente
Seq
es covariante ... ¿me falta algo?Array[Any]
internamente.EDITAR : para cualquiera que se pregunte por qué esta respuesta parece un poco fuera de tema, esto se debe a que yo (el interrogador) he modificado la pregunta.
La inferencia de tipos de Scala es lo suficientemente buena como para darse cuenta de que desea CharSequences y no Strings en algunas situaciones. En particular, lo siguiente me funciona en 2.7.3:
En cuanto a cómo crear inmutables.HashSets directamente: no lo hagas. Como optimización de implementación, inmutable.HashSets de menos de 5 elementos no son realmente instancias de inmutable.HashSet. Son EmptySet, Set1, Set2, Set3 o Set4. Estas clases son una subclase de inmutable.Set, pero no inmutable.HashSet.
fuente