为什么 Scala 的不可变 Set 的类型不是协变的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/676615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is Scala's immutable Set not covariant in its type?
提问by oxbow_lakes
EDIT: Re-written this question based on original answer
编辑:根据原始答案重写此问题
The scala.collection.immutable.Setclass is not covariant in its type parameter. Why is this?
该scala.collection.immutable.Set班是不是在它的类型参数不变性。为什么是这样?
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
}
采纳答案by Daniel Spiewak
Setis invariant in its type parameter because of the concept behind sets as functions. The following signatures should clarify things slightly:
Set由于集合作为函数背后的概念,它的类型参数是不变的。以下签名应该稍微澄清一下:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
If Setwere covariant in A, the applymethod would be unable to take a parameter of type Adue to the contravariance of functions. Setcould potentially be contravariantin A, but this too causes issues when you want to do things like this:
如果Set是协变的A,则由于函数的逆变,该apply方法将无法采用类型参数A。 Set可能是逆变的A,但是当您想要执行以下操作时,这也会导致问题:
def elements: Iterable[A]
In short, the best solution is to keep things invariant, even for the immutable data structure. You'll notice that immutable.Mapis also invariant in one of its type parameters.
简而言之,最好的解决方案是保持事物不变,即使对于不可变的数据结构也是如此。您会注意到immutable.Map它的类型参数之一也是不变的。
回答by Seth Tisue
at http://www.scala-lang.org/node/9764Martin Odersky writes:
在http://www.scala-lang.org/node/9764Martin Odersky 写道:
"On the issue of sets, I believe the non-variance stems also from the implementations. Common sets are implemented as hashtables, which are non-variant arrays of the key type. I agree it's a slightly annoying irregularity."
“关于集合的问题,我相信非方差也源于实现。公共集合被实现为哈希表,它是键类型的非变异数组。我同意这是一个有点烦人的不规则性。”
So, it seems that all of our efforts to construct a principled reason for this were misguided :-)
因此,似乎我们为此构建原则性原因的所有努力都被误导了:-)
回答by Jorge Ortiz
EDIT: for anyone wondering why this answer seems slightly off-topic, this is because I (the questioner) have modified the question.
编辑:对于任何想知道为什么这个答案似乎有点离题的人,这是因为我(提问者)修改了这个问题。
Scala's type inference is good enough to figure out that you want CharSequences and not Strings in some situations. In particular, the following works for me in 2.7.3:
Scala 的类型推断足以确定在某些情况下您需要 CharSequences 而不是 Strings。特别是,以下内容在 2.7.3 中对我有用:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
As to how to create immutable.HashSets directly: don't. As an implementation optimization, immutable.HashSets of less than 5 elements are not actually instances of immutable.HashSet. They are either EmptySet, Set1, Set2, Set3, or Set4. These classes subclass immutable.Set, but not immutable.HashSet.
至于如何直接创建 immutable.HashSets:不要。作为实现优化,少于 5 个元素的 immutable.HashSets 实际上并不是 immutable.HashSet 的实例。它们是 EmptySet、Set1、Set2、Set3 或 Set4。这些类是 immutable.Set 的子类,但不是 immutable.HashSet。

