EDIT : Tulis ulang pertanyaan ini berdasarkan jawaban asli
The scala.collection.immutable.Set
kelas tidak kovarian dalam parameter jenisnya. Kenapa ini?
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
}
scala
set
covariance
scala-collections
oxbow_lakes
sumber
sumber
foo(s.toSet[CharSequence])
kompilasi baik-baik saja. ThetoSet
metode adalah O (1) - itu hanya membungkusasInstanceOf
.foo(Set("Hello", "World"))
mengkompilasi juga pada 2.10, karena Scala tampaknya dapat menyimpulkan jenis Set yang tepat. Ini tidak bekerja dengan konversi implisit sekalipun ( stackoverflow.com/questions/23274033/… ).Jawaban:
Set
adalah invarian dalam parameter tipenya karena konsep di balik himpunan sebagai fungsi. Tanda tangan berikut harus sedikit menjelaskan hal-hal:trait Set[A] extends (A=>Boolean) { def apply(e: A): Boolean }
Jika
Set
kovarian masukA
,apply
metode tidak akan dapat mengambil parameter tipeA
karena pertentangan fungsi.Set
berpotensi menjadi contravariant diA
, tapi ini terlalu menyebabkan masalah ketika Anda ingin melakukan hal-hal seperti ini:def elements: Iterable[A]
Singkatnya, solusi terbaik adalah menjaga hal-hal tetap tidak berubah, bahkan untuk struktur data yang tidak dapat diubah. Anda akan melihat bahwa
immutable.Map
itu juga tidak berubah di salah satu parameter tipenya.sumber
List(1,2,3).contains _
adalah(Any) => Boolean
, sedangkan jenisnyaSet(1,2,3).contains _
adalahres1: (Int) => Boolean
.di http://www.scala-lang.org/node/9764 Martin Odersky menulis:
Jadi, tampaknya semua upaya kami untuk membangun alasan yang berprinsip untuk ini salah arah :-)
sumber
Seq
kovarian ... apakah saya melewatkan sesuatu?Array[Any]
internal.EDIT : bagi siapa pun yang bertanya-tanya mengapa jawaban ini tampak sedikit di luar topik, ini karena saya (penanya) telah mengubah pertanyaannya.
Jenis inferensi Scala cukup baik untuk mengetahui bahwa Anda menginginkan CharSequences dan bukan Strings dalam beberapa situasi. Secara khusus, berikut ini berfungsi untuk saya di 2.7.3:
import scala.collections.immutable._ def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
Mengenai cara membuat immutable.HashSets secara langsung: jangan. Sebagai pengoptimalan implementasi, immutable.HashSet yang kurang dari 5 elemen sebenarnya bukan instance dari immutable.HashSet. Mereka adalah EmptySet, Set1, Set2, Set3, atau Set4. Kelas-kelas ini merupakan subkelas immutable.Set, tetapi tidak immutable.HashSet.
sumber