Scala :: for comprehension和自由变量

时间:2017-03-01 19:13:26

标签: scala for-comprehension

我需要将一堆返回Either[String, X]的函数包装成for-comprehension,并且还需要使用一些纯函数转换一些调用的结果,并将这些结果缓存到临时变量中

以下(非常人为的)代码无法编译

1: def someFunc(x: Int): Either[String, Int] = Right(x)
2: 
3: def someMath(i: Int): Int = i
4: 
5: val z = for {
6:  x <- Right("aaaa").right
7:  y <- Right((1, x)).right
8:  tmp = someMath(y._1)
9:  t <- Right(tmp).right
A:  l <- someFunc(tmp).right
B: } yield l
C: 
D: z
  

错误:(7,6)value flatMap不是Product with的成员   可以使用scala.util.Either [Nothing,((Int,String),Int)] y进行序列化   &lt; - 右((1,x))。右       ^

如何在for {...}表达式中定义任意类型的变量(不是Either)?

2 个答案:

答案 0 :(得分:0)

在scala 2.12中,Either是可以使用for组成的monadic类型,因此以下工作:

val z = for {
  x <- Right("aaa")
  y <- Right((1, x))
 ...
}

正如@jdevelop在评论中提到的,这在2.10或2.11

中不起作用

如果您的Left类型是个例外,则Try是一个不错的选择。如果你需要一个Either的可移植版本,那么写一个就不难了,就像那样烦人。

答案 1 :(得分:0)

您可以有一个像这样的隐式转换器:

  implicit class EitherOps[A,B](val e: Either[A,B]) extends AnyVal {
    def flatMap[A1 >: A, B1](f: B => Either[A1, B1]): Either[A1, B1] = e.right.flatMap(f)
    def map[B1](f: B => B1): Either[A, B1] = e.right.map(f)
  }

使任一权利都像Scala 2.12+中那样有偏见。 您应该仅将其用于Scala 2.11。 这样,您也可以使用与2.12和2.11中相同的全面代码。