2011-04-29 1 views
7

Avec Scala 2.8.1, compilation ceci:Pourquoi cette classe Scala pour l'utilisation de tuples ne peut-elle pas être compilée?

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) 

donne ceci:

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) 

Selon Programmation en Scala, l'expression for devrait être équivalente à l'expression carte/cas, mais seul ce dernier compile. Qu'est-ce que je fais de mal, et comment dois-je faire cela?

Répondre

11

En fait, ce n'est pas tout à fait la traduction qui se passe. Vous pouvez vous référer à this answer pour un guide plus complet, mais ce cas n'est pas explicitement mentionné même là.

Qu'est-ce qui se passe est que pour la compréhension avec filtrage de filtres filtre le cas non-correspondant. Par exemple,

for((i, j) <- List((1, 2), 3)) yield (i, j) 

retournera List((1, 2)): List[(Any, Any)], comme withFilter est appelé en premier. Maintenant, Either ne semble pas avoir withFilter, il utilisera filter, et voici la traduction réelle de cette compréhension pour:

e.right.filter { case (i, j) => true; case _ => false }.map { case (i, j) => i + j } 

Ce qui donne exactement la même erreur. Le problème est que e.right renvoie un RightProjection, mais filter sur RightProjection[A, B] renvoie Option[Either[Nothing, B]].

La raison est qu'il n'y a pas une telle chose comme un « vide » Either (ou RightProjection), il doit résumer le résultat sur un Option.

Ayant dit tout cela, il est vraiment surprenant lorsqu'on regarde le niveau de compréhension. Je pense que la bonne chose serait pour filter de renvoyer une sorte de projection filtrée à la place.

2

Le droit ne renvoie pas l'option que vous pourriez attendre, mais une RightProjection. Cela corrige le:

println(for ((i, j) <- e.right.toOption) yield i + j) 
Questions connexes