使用for with选项仅适用于某些情况

时间:2014-11-15 15:57:19

标签: scala

如果我写这个:

val (x, y) = (Some(8), None)
def f(x: Int, y: Int) = x + y

for {x0 <- x; y0 <- y} yield f(x0, y0)

我收到了预期的结果:res5: Option[Int] = None

但如果我试着写:

for {x0 <- x; y0 <- y} yield (x0 + y0)

我收到下一个错误:

<console>:10: 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)
          for {x0 <- x; y0 <- y} yield (x0 + y0)

有人可以解释我为什么我的最后一次尝试不起作用吗?我可能在如何使用和选项工作的内部遗漏了一些东西。 x0应为Int,不应该吗?

3 个答案:

答案 0 :(得分:5)

将其粘贴到REPL中会清楚表明y不是Option[Int]

scala> val (x, y) = (Some(8), None)
x: Some[Int] = Some(8)
y: None.type = None

编译器不能以None的形式推断Option[T]而不明确告知None.type,因此它被推断为scala> val (x, y) = (Some(8), Option.empty[Int]) x: Some[Int] = Some(8) y: Option[Int] = None 。您应该使用显式类型注释:

val (x, y): (Option[Int], Option[Int]) = (Some(8), None)

{{1}}也可以。

答案 1 :(得分:2)

其他答案已经说明如何修复错误;我将详细介绍为什么你会得到错误。

x0Int; y0不是Nothing,因为None extends Option[Nothing])。 Nothing是每种类型的子类型,包括可添加到Int的所有类型,例如ByteChar(如消息所示)。因此,编译器不知道它应该使用哪个+。即使它实际上并不重要(所有这些都会导致None),但这仍然是一个错误。

答案 2 :(得分:1)

问题是y的类型是 Option [Int](正如您所料)但是没有。

val (x, y) = (Some(8), Some(4))

for {x0 <- x; y0 <- y} yield (x0 + y0)

工作得很好。所以在任何现实世界的用例中(其中x和y是Option [Int]),这将很好。这只是因为你有一个明确的无,编译器有点困惑。