Say I have a simple class like this
abstract class Foo {
implicit val impInt: Int = 42
def f[A]()(implicit a: A): A
val f2: Int = f()
}
When declaring val f2
, compiler is able to infer that the type of implicit parameter of function f
is Int
because that type is the same as the result type, and result type needs to match the type of value f2
, which is Int
.
However, throwing an Ordering[A]
into the mix:
def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
results in this compile error:
Ambiguous implicit values: both value StringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String] and method $conforms in object Predef of type [A]=> <:<[A,A] match expected type A
If I add the type information when invoking f()
, it compiles:
val f2: Int = f[Int]()
First I encountered the case with implicit ordering and I thought it has to do with Scala inferring left-to-right; I thought it's not able to match the return type first and then infer the (implicit) parameter type of f
. But then I tried the case without implicit ordering and saw that it works - it inferred that f
must be parameterized by Int
because the return type has to be an Int
(because f2
is an Int
).
Note that if we remove implicit a: A
and leave only the Ordering implicit parameter, the error remains, but becomes
Diverging implicit expansion for type Ordering[A] starting with method Tuple9 in object Ordering.
Again, adding type parameter so that it becomes val f2: Int = f[Int]()
helps.
What's going on? Why can the compiler infer that parameter A
must be an Int
, but not that parameter Ordering[A]
must be an Ordering[Int]
?