Pergunta

Editar : Re-escrito esta questão com base na resposta original

A classe scala.collection.immutable.Set não é covariante em seu parâmetro de tipo. Por que é isso?

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

Solução

Set é invariante em seu parâmetro de tipo por causa do conceito por trás conjuntos como funções. As assinaturas a seguir deve esclarecer as coisas um pouco:

trait Set[A] extends (A=>Boolean) {
  def apply(e: A): Boolean
}

Se Set eram covariant em A, o método apply seria incapaz de tomar um parâmetro do tipo A devido à contravariance de funções. Set poderia ser contravariant em A, mas isso também causa problemas quando você quer fazer coisas como esta:

def elements: Iterable[A]

Em suma, a melhor solução é manter as coisas invariável, mesmo para a estrutura de dados imutáveis. Você notará que immutable.Map também é invariante em um de seus parâmetros de tipo.

Outras dicas

em http://www.scala-lang.org/node/9764 Martin Odersky escreve:

"Sobre a questão de conjuntos, acredito que o não-variação decorre também das implementações. Conjuntos comuns são implementados como tabelas de hash, que são matrizes não-variantes do tipo de chave. Concordo que é uma irregularidade ligeiramente irritante."

Assim, parece que todos os nossos esforços para construir uma razão de princípios para este foram equivocados: -)

Editar : para qualquer um se perguntando por que esta resposta parece um pouco off-topic, isso é porque eu (o inquiridor) ter modificado a questão.

inferência de tipos do Scala é bom o suficiente para descobrir o que você quer CharSequences e não Cordas em algumas situações. Em particular, as seguintes obras para mim em 2.7.3:

import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")

Quanto à forma de criar immutable.HashSets diretamente: não. Como uma otimização de implementação, immutable.HashSets de menos de 5 elementos não são na verdade casos de immutable.HashSet. Eles são ou emptyset, Set1, Set2, Set3, ou Set4. Essas classes de subclasse immutable.Set, mas não immutable.HashSet.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top