¿Por qué es inmutable Conjunto de Scala no covariantes en su tipo?
-
21-08-2019 - |
Pregunta
Editar : Re-escrito esta pregunta basada en respuesta original
El scala.collection.immutable.Set
clase no se 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
}
Solución
Set
es invariable en su parámetro de tipo a causa del concepto detrás de juegos como funciones. Las firmas siguientes deben aclarar un poco las cosas:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
Si A
eran covariante en apply
, el método immutable.Map
sería incapaz de tomar un parámetro de tipo <=> debido a la contravarianza de funciones. <=> puedan contener contravariant en <=>, pero esto también causa problemas cuando se quiere hacer cosas como esta:
def elements: Iterable[A]
En resumen, la mejor solución es mantener las cosas invariables, incluso para la estructura de datos inmutables. Se dará cuenta de que <=> también es invariante en uno de sus parámetros de tipo.
Otros consejos
http://www.scala-lang.org/node/9764 escribe Martin Odersky:
"En el tema de juegos, creo que el no-varianza se deriva también de las implementaciones. Los conjuntos comunes se implementan como tablas hash, que son matrices no variante del tipo de clave. Estoy de acuerdo en que es una irregularidad poco molesto."
Por lo tanto, parece que todos nuestros esfuerzos para construir una razón de principio para esto fuera equivocada: -)
Editar : para cualquiera que se pregunte por qué esta respuesta parece un poco fuera de tema, esto se debe a que (el interrogador) he modificado la pregunta.
inferencia de tipos de Scala es lo suficientemente bueno para averiguar que desea CharSequences y no cadenas en algunas situaciones. En particular, las siguientes obras para mí en 2.7.3:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
En cuanto a la forma de crear directamente immutable.HashSets: no. Como una optimización aplicación, immutable.HashSets de menos de 5 elementos que no son en realidad casos de immutable.HashSet. Son ya sea emptyset, set1, Set2, Set3 o Set4. Estas clases subclasifican immutable.Set, pero no immutable.HashSet.