Search code examples
scalaoption-typefor-comprehension

Scala for-comprehension and Option


object main {
  def main(args: Array[String]) = {
    val x = Option(2)
    val y = None // works with: Option.empty[Int]
    val z = Option(5)

    val result1 = for {
      x <- x
      y <- y
      z <- z
    } yield {
      (x, y, z, x + y + z, x * y * z)
    }

    println(result1)
  }
}

This code yields an exception:

example.scala:14: error: ambiguous reference to overloaded definition,
both method * in class Int of type (x: Char): Int
and  method * in class Int of type (x: Byte): Int
match argument types (Nothing)
      (x, y, z, x + y + z, x * y * z)

If we use val y = Option.empty[Int] instead of val y = None, it works in the sense that result1 contains None.

But why are there any restrictions on the function * ? We don't get (2, None, 5, None, None) anyway. I assumed the step would be skipped if one value was None, so why must * unambiguously refer to a definition?


Solution

  • The error happens because y has type None which extends Option[Nothing].

    In the for comprehension, the inner y thus has a Nothing type and you cannot apply * to Nothing.

    The error goes away if you explicitly type (outer) y to Option[Int]:

    val y: Option[Int] = None
    

    When you say:

    assumed the step would be skipped if one value was None

    This is true at runtime, but at compile time the compiler only sees a combination of Option[Int] and Option[Nothing].