Ответ 1
Как ни парадоксально, первая версия работает, потому что subsets
в приложении subsets(2)
как бы более двусмысленна, чем без парнеров.
Поскольку метод перегружен, в приложении компилятор останавливается для решения для B
результата toSet
и решает, что B
есть Int
. Поэтому он знает, какой тип параметра ожидается для map
.
В версии без парнеров метод с списком параметров не является кандидатом, потому что эта-расширение не запускается. Поэтому, когда он набирает приложение map
, он не сделал никаких выводов о B
, который является типом ввода для функции сопоставления.
Легкое исправление заключается в том, чтобы сказать ему, чтобы вывести B
:
trait Test {
def f1 = List(1, 2, 3).to[Set].subsets.map(_.toList) // instead of .toSet
def f2 = List(1, 2, 3).toSet.subsets(2).map(_.toList)
}
Вывод -Ytyper-debug
в исходном коде показывает, как перегрузка разрешает тип вывода типа:
| | | | | | \-> => Iterator[scala.collection.immutable.Set[B]] <and> (len: Int)Iterator[scala.collection.immutable.Set[B]]
| | | | | solving for (B: ?B)
| | | | | |-- 2 : pt=Int BYVALmode-EXPRmode-POLYmode (silent: method f2 in Test)
| | | | | | \-> Int(2)
| | | | | solving for (B: ?B)
| | | | | \-> Iterator[scala.collection.immutable.Set[Int]]
Другим обходным путем является использование метода расширения:
scala> implicit class ss[A](val s: Set[A]) { def ss(n: Int) = s subsets n ; def ss = s.subsets }
defined class ss
scala> List(1, 2, 3).toSet.ss.map(_.toList)
res1: Iterator[List[Int]] = non-empty iterator
Посмотрим, не изменится ли библиотека: