How to make Scala type inference powerful enough t

2019-09-18 14:19发布

问题:

Assuming that I defined a function that takes implicit TypeTag:

  def andOptionFn[A: TypeTag](g: Int => Option[A]) = {
    val ttg = ScalaReflection.universe.typeTag[A]
    println(ttg)
    ...
  }

And call it:

andOptionFn{
v =>
  Some(v)
}

I would expect scala type inference to get the correct type TypeTag(Option(Int)), but instead I got:

TypeTag(Option(Any)) (not even a higher kind)

Why Scala is unable to infer it automatically in compilation time? and what works needs to be done to improve it?

回答1:

The correct result is TypeTag[Int], and Scala does print it: http://scastie.org/20273 (after you replace ScalaReflection with scala.reflect.runtime; if ScalaReflection is your own class, that's where you should look for the problem).

EDIT: http://scastie.org/20293 isn't a bug, it's type inference behaving precisely as designed. Call to Seq.apply[Option[_]] gives the expected type of Option[_] to each argument. When

andOptionFn {
  v =>
    if (v > 1) Some(v)
    else None
}

is typechecked with this expected type, the inferred R is of course Any.

EDIT 2: After reading http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference more carefully, it does seem like it should infer Int after all, but I am not certain. What I thought is that Option[_] gets reduced to Option[Any] (because Option is covariant), in which case Any should certainly be inferred. But http://scastie.org/20293 and http://scastie.org/20295 should behave the same, so there is at least one bug (I think) :)