使用Scala 2.8.1,编译:
val t = (40, 2)
println(for ((i, j) <- List(t)) yield i + j)
val e: Either[String, (Int, Int)] = Right(t)
println(e.right.map {
case (i, j) => i + j
})
println(for ((i, j) <- e.right) yield i + j)
给出了这个:
test.scala:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: Either[Nothing,(Int, Int)]
println(for ((i, j) <- e.right) yield i + j)
根据Scala中的 Programming ,for表达式应该等同于map / case表达式,但只有后者才能编译。我做错了什么,我应该怎么做?
答案 0 :(得分:11)
实际上,这不是完全正在发生的翻译。您可以参考this answer获取更完整的指南,但即使在那里也没有明确提及此案例。
对于使用模式匹配的理解,过滤不匹配的情况会发生什么。例如,
for((i, j) <- List((1, 2), 3)) yield (i, j)
将返回List((1, 2)): List[(Any, Any)]
,因为首先调用withFilter
。现在,Either
似乎没有withFilter
,所以它会使用filter
,而这里是理解的实际翻译:
e.right.filter { case (i, j) => true; case _ => false }.map { case (i, j) => i + j }
这给出了完全相同的错误。问题是e.right
会返回RightProjection
,但filter
上的RightProjection[A, B]
会返回Option[Either[Nothing, B]]
。
原因是没有“空”Either
(或RightProjection
)这样的东西,所以需要将其结果封装在Option
上。
说了这么多,看看for-comprehension水平真是令人惊讶。我认为正确的做法是让filter
返回某种过滤后的投影。
答案 1 :(得分:2)
Right不会返回您可能期望的选项,而是返回RightProjection。这解决了它:
println(for ((i, j) <- e.right.toOption) yield i + j)