Paradoxically, the first version works because subsets
in the application subsets(2)
is, as it were, more ambiguous than without parens.
Because the method is overloaded, in the application, the compiler pauses to solve for the B
result of toSet
, and decides that B
is Int
. So it knows what param type is expected for the map
.
In the version without parens, the method with a parameter list is not a candidate, because eta-expansion is not triggered. So when it types the map
application, it has not drawn any conclusions about B
, which is the input type to the mapping function.
The easy fix is to tell it to deduce B
:
trait Test {
def f1 = List(1, 2, 3).to[Set].subsets.map(_.toList)
def f2 = List(1, 2, 3).toSet.subsets(2).map(_.toList)
}
The output of -Ytyper-debug
on the original code shows how overload resolution gooses type inference:
| | | | | | \-> => 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]]
Another workaround is to go through an extension method:
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
Let's see if they'll take the library change:
https://github.com/scala/scala/pull/4270
.subsets
is more ambiguous (it could be a partial application of the version that takes an argument), so type inference works less well. In any case you can make it compile by doing what the compiler tells you and providing an explicit type:List(1, 2, 3).toSet.subsets.map{x: Set[Int] => x.toList}
– lmmdef subsets: Iterator[Set[A]]
,def subsets(len: Int): Iterator[Set[A]]
So there should not be any difference, as far as types as concerned, right? – the21stdef subsets(i: Int)(d: Double): Iterator[Set[A]]
would cause anambiguous reference to overloaded definition
error? – Jasper-MSet(1, 2, 3).subsets
it works. If you break it up with...subsets match { case x => x.map(_.toList) }
it also works. – Rex Kerrsubsets
could be a partial application ofsubsets(Int)
, whereassubsets(2)
could not be a partial application ofsubsets
. (But it's just a guess). – lmm