Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

scala - Inferring type of generic implicit parameter from return type

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]?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There must be something wrong with the way ordering instances are generated, as the code below works. I'd report a bug.

case object types {
  implicit def buh[X]: List[X] = List()
}
abstract class Foo {

  import types._

  def f[A]()(implicit l: List[A]): A
  val f2: Int = f()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...