Michal Rus
Michal Rus

Reputation: 1848

Infer a return type of a method based on the type expected in call site?

So, basically, what I want to do is:

object WithoutWrap {

  def f[T: ClassTag](x: String): T = {
    println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
    ??? : T
  }

  def y: Int = f("abc")
  def z: Int = f[Int]("abc")

}

In both cases I’d like the inferred T to be Int. Let’s run this:

scala> WithoutWrap.y
Class of T is really… Nothing
scala.NotImplementedError: an implementation is missing

scala> WithoutWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing

Unfortunately it’s Nothing in the first case.

However, if we return the T wrapped in something,

object WithWrap {

  trait Wrap[T]

  def f[T: ClassTag](x: String): Wrap[T] = {
    println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
    ??? : Wrap[T]
  }

  def y: Wrap[Int] = f("abc")
  def z: Wrap[Int] = f[Int]("abc")

}

… the T is inferred correctly in both cases:

scala> WithWrap.y
Class of T is really… Int
scala.NotImplementedError: an implementation is missing

scala> WithWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing

How to get Int in both cases without wrapping?

Upvotes: 2

Views: 136

Answers (1)

som-snytt
som-snytt

Reputation: 39577

Depending on what you're trying to accomplish, overload resolution is sensitive to expected type:

scala> case class A(s: String) ; case class B(s: String)
defined class A
defined class B

scala> :pa
// Entering paste mode (ctrl-D to finish)

object X {
def f(s: String): A = A(s)
def f(s: String)(implicit d: DummyImplicit): B = B(s)
}

// Exiting paste mode, now interpreting.

defined object X

scala> val x: A = X f "hi"
x: A = A(hi)

scala> val y: B = X f "hi"
y: B = B(hi)

Upvotes: 1

Related Questions