如果我写这个:
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
,不应该吗?
答案 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)
其他答案已经说明如何修复错误;我将详细介绍为什么你会得到错误。
x0
是Int
; y0
不是Nothing
,因为None extends Option[Nothing]
)。 Nothing
是每种类型的子类型,包括可添加到Int
的所有类型,例如Byte
和Char
(如消息所示)。因此,编译器不知道它应该使用哪个+
。即使它实际上并不重要(所有这些都会导致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]),这将很好。这只是因为你有一个明确的无,编译器有点困惑。