jest to skomplikowany wpływ mieszania kowariantna i zbiory niezmienne. Zestaw jest niezmienny: Set[A]
. Ale Seq jest kowariancyjny: Seq[+A]
. Teraz wyobraź sobie, że chcesz mieć metodę toSet
w swoim Seq. Możesz spróbować toSet: Set[A]
. Ale to nie zadziała, ponieważ jeśli A
jest podklasą B
, wówczas Seq[A]
należy uznać za podklasę Seq[B]
. Jednakże, Seq[A]
nalega na zwrócenie Set[A]
, która jest podklasą 2 podklasy . Więc nasze pisanie jest zepsute.
Jeśli, z drugiej strony, możemy określić toSeq[B >: A]: Set[B]
wtedy wszystko jest w porządku: jeśli obiecujemy możemy wrócić żadnych superklasę, następnie Seq[A]
może powrócić Set[B]
jak również Set[C]
gdzie C
jest nadklasą B
. Seq[B]
obiecał również zwrócić Set[B]
lub niektóre Set[C]
również, więc nie mamy żadnych wątpliwości: metoda na Seq[A]
może zrobić wszystko, co może zrobić metoda na Seq[B]
.
Ale teraz spojrzeć na to, co biedny typer ma do czynienia z:
s.toSet[B >: I]
.toSeq/* Type B >: I*/
.sortBy[C](/* some f:B => C */)(/* implicit ordering on C */)
Nie jest sposób, aby rozwiązać ten problem - mianowicie zdecydować, że B
jest I
i wpisać funkcję i C
odpowiednio. Ale to dość skomplikowane wyszukiwanie i to więcej niż kompilator może obsłużyć w tej chwili. Dlatego prosi o pomoc przy typie wejścia do funkcji, aby w tym momencie wiedział, B
(a następnie może przekazać go z powrotem do toSet
).
Ale może, jeśli chce, poradzić się w wielu płaszczyznach:
s.toSet[I].toSeq.sortBy(_.i)
s.toSet.toSeq.sortBy[Int](_.i)
lub można go pomóc poprzez wykazanie mu, że nie musi brać pod uwagę nowsze typy podczas wybierania najlepszego dopasowania z wcześniejszymi typami:
{ val temp = s.toSet; temp }.toSeq.sortBy(_.i)
s.toSet match { case x => x.toSeq.sortBy(_.i) }
Rex, dzięki za to oświecenie, tego właśnie chciałem. Takie odpowiedzi nie tylko rozwiązują problem, ale także pozwalają lepiej zrozumieć, co się dzieje. Dziękuję Ci bardzo! Jaka szkoda, można tylko raz głosować: D –