为什么Scala的不可变集合在它的types中不是协变的?

编辑 :根据原来的答案重新写这个问题

scala.collection.immutable.Set类在其types参数中不是协变的。 为什么是这样?

 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 } 

由于设置为函数的概念,set的types参数是不变的。 以下签名应该略微澄清一些事情:

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

如果SetA是协变A ,则由于函数的变换, apply方法将不能取Atypes的参数。 A可能在A可逆 A ,但是当你想要做这样的事情时,这也会导致问题:

 def elements: Iterable[A] 

总之,最好的解决scheme是保持事物不变,即使对于不可变的数据结构。 你会注意到immutable.Map在其types参数中也是不变的。

http://www.scala-lang.org/node/9764 Martin Odersky写道:

“关于集合的问题,我相信这种非变异也来自于实现,通用集合是作为哈希表来实现的,哈希表是关键types的非variables数组,我同意这是一个有点烦人的不规则性。

所以,我们所有为此构build原则性理由的努力都被误导了:-)

编辑 :任何人想知道为什么这个答案似乎有点离题,这是因为我(提问者)已经修改了这个问题。

Scala的types推断足以certificate在某些情况下你需要CharSequences而不是Strings。 特别是,下面的2.7.3中为我工作:

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

至于如何直接创buildimmutable.HashSets:不。 作为一个实现优化,less于5个元素的immutable.HashSets实际上并不是immutable.HashSet的实例。 它们是EmptySet,Set1,Set2,Set3或Set4。 这些类是不可变的。设置,但不是immutable.HashSet。