Парадоксально, первая версия работает, потому что 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
Давайте посмотрим, если они будут принимать изменения библиотеки:
https://github.com/scala/scala/pull/4270
Я предположил бы, что '.subsets' более неоднозначная (это может быть частичным применением версии, которая принимает аргумент), так типа вывод работает не так хорошо. В любом случае вы можете скомпилировать его, выполнив то, что говорит вам компилятор, и предоставив явный тип: 'List (1, 2, 3) .toSet.subsets.map {x: Установить [Int] => x.toList}' – lmm
Но два метода имеют одну и ту же подпись типа возврата, согласно 2.10.4 scaladoc: 'def subsets: Iterator [Set [A]]', 'def subsets (len: Int): Iterator [Set [A]]' Таким образом, не должно быть никаких различий в отношении типов , правильно? – the21st
Разве это не несогласованность в Scala, что эти методы разрешены вместе, в то время как метод 'def subsets (i: Int) (d: Double): Iterator [Set [A]]' приведет к «неоднозначной ссылке на перегруженное определение» ошибка? –