[〜#〜] edit [〜#〜]:元の回答に基づいてこの質問を書き直しました
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
}
Set
は、関数としてのセットの背後にある概念のため、その型パラメーターは不変です。次の署名は、物事をわずかに明確にする必要があります。
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
Set
がA
で共変である場合、関数の共変性のために、apply
メソッドはタイプA
のパラメーターを受け取ることができません。 Set
は潜在的にcontravariant in A
である可能性がありますが、これも次のようなことをしたいときに問題を引き起こします。
def elements: Iterable[A]
要するに、最良の解決策は、不変のデータ構造であっても、物事を不変に保つことです。 immutable.Map
は、その型パラメーターの1つでも不変です。
at http://www.scala-lang.org/node/9764 Martin Oderskyは次のように書いています:
「セットの問題については、非分散は実装にも起因すると思います。一般的なセットは、キータイプの非分散配列であるハッシュテーブルとして実装されます。少し厄介な不規則性であることに同意します。」
したがって、これの原則的な理由を構築するための私たちのすべての努力は誤った方向に進んだようです:-)
[〜#〜] edit [〜#〜]:なぜこの回答が少し話題から外れているのか疑問に思っている人にとっては、これは私(質問者)が質問を変更したためです。
Scalaの型推論は、状況によっては文字列ではなくCharSequencesが必要であることを理解するのに十分です。特に、2.7.3では次のことがうまくいきます。
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
Immutable.HashSetsを直接作成する方法については、しないでください。実装の最適化として、5要素未満のimmutable.HashSetは、実際にはimmutable.HashSetのインスタンスではありません。それらは、EmptySet、Set1、Set2、Set3、またはSet4のいずれかです。これらのクラスはimmutable.Setをサブクラス化しますが、immutable.HashSetはサブクラス化しません。