2011-04-29 26 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) 
相關問題