98

編集:元の回答に基づいてこの質問を書き直しました

クラスは、その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
}
4

3 に答える 3

57

Set関数としてのセットの背後にある概念のため、型パラメーターは不変です。次の署名は、物事をわずかに明確にする必要があります。

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

Setが共変である場合、関数の反変性のためAに、applyメソッドは型のパラメーターを受け取ることができませんAで反変Setなる可能性がありますが、次のようなことをしたい場合にも問題が発生します。A

def elements: Iterable[A]

要するに、最善の解決策は、不変のデータ構造であっても、物事を不変に保つことです。immutable.Mapこれは、その型パラメーターの1つでも不変であることに気付くでしょう。

于 2009-03-24T18:34:16.317 に答える
53

http://www.scala-lang.org/node/9764でMartin Odersky は次のように書いています。

「セットの問題については、非分散性は実装にも起因すると考えています。一般的なセットは、キー型の非バリアント配列であるハッシュテーブルとして実装されています。少し面倒な不規則性であることに同意します。」

したがって、これに対する原則的な理由を構築するための私たちの努力はすべて見当違いだったようです:-)

于 2011-05-31T04:49:17.753 に答える
6

編集:なぜこの回答が少し話題から外れているように見えるのか疑問に思っている人のために、これは私(質問者)が質問を変更したためです。

Scalaの型推論は、状況によってはStringsではなく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はサブクラス化しません。

于 2009-03-24T10:45:02.577 に答える