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
}
¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top