我发现"对重载定义的模糊引用";在尝试练习scala面试问题时。
我试图找到导致编译错误的以下代码块的结果:
代码:
for {
v1 <- Left[Int,Int](1)
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left(4)
} yield v1 + v2 + v3 + v4
错误:
<pastie>:17: 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)
} yield v1 + v2 + v3 + v4
^
当我们只在v1字段上指定类型,而不在v4上指定类型时,为什么Scala编译器会给不明确的引用错误?
我还在v1和v4中尝试了以下不同参数类型的版本,结果成功了!
for {
v1 <- Left[String,Int]("1")
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left[Int, Int](4)
} yield v1 + v2 + v3 + v4
输出为:
res20: scala.util.Either[Any,Int] = Left(1)
我尝试了另一个版本,但也导致了错误:
for {
v1 <- Left(1)
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left(4)
} yield v1 + v2 + v3 + v4
输出:
<console>:17: error: value + is not a member of Nothing
} yield v1 + v2 + v3 + v4
对于理解,在这里Left
和Right
究竟是如何工作的?为什么第一个和最后一个案例在我的例子中不起作用?
这是因为没有常见的推断类型,并且您没有为所有Either
指定类型。
所以
scala> for (v1 <- Right(2)) yield v1
res13: scala.util.Either[Nothing,Int] = Right(2)
解决方案是给他们提供常见类型的
for {
v1 <- Left[Int,Int](1)
v2 <- Right[Int,Int](2)
v3 <- Right[Int,Int](3)
v4 <- Left[Int,Int](4)
} yield v1 + v2 + v3 + v4
从而得到CCD_ 4。这一结果是有意义的,因为Either
是右偏的,并且对于作为flatMap
的理解来说。
根据文件:"任意一个都是右偏的,这意味着right被认为是操作的默认情况。如果是Left,则map、flatMap等操作。。。返回Left值不变">
https://www.scala-lang.org/api/2.12.0/scala/util/Either.html