2011-04-29 62 views
7

使用Scala 2.8.1,编译此:为什么Scala使用元组进行表达无法编译?

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中编程,所述用于表达应相当于在地图/情况下表达,但是只有后者才会编译。我做错了什么,我该怎么做?

回答

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,但filterRightProjection[A, B]返回Option[Either[Nothing, B]]

原因是没有“空”Either(或RightProjection)这样的东西,所以它需要将其结果封装在Option上。

说了这么多之后,当看到理解水平时,确实令人惊讶。我认为filter会正确的返回某种滤镜投影。

2

Right没有返回您可能期望的选项,而是RightProjection。这修复它:

println(for ((i, j) <- e.right.toOption) yield i + j) 
相关问题