如何在功能上干净地检查Scala中的错误?

use*_*352 0 functional-programming scala

在检查错误而不简单地链接函数时,有没有办法避免下面代码中的嵌套?

val a: Either[Value, Exception]
val b: Either[Value, Exception]
val c: Either[Value, Exception]

def combine(a: Either[Value, Exception], 
            b: Either[Value, Exception], 
            c: Either[Value, Exception]) = 
{
  a match {
    case Right(a) => Right(a)
    case Left(a)  => b match {
                       case Right(b) => Right(b)
                       case Left(b)  => c match {
                                          case Right(c) => Right(c)
                                          case Left(c)  => a + b + c
                                        }
                     }
   }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*zok 5

第一:按照惯例(从 Haskell 导入,它更有意义)错误是Left,正确的值是Right.

一旦我们建立了这个约定:.map允许映射正确的值(它使Left值保持不变)同时.flatMap允许您将Right值转换为LeftRight- 在Right它上面将继续组合,同时Left将破坏电路。

拥有:

val a: Either[Exception, Value]
val b: Either[Exception, Value]
val c: Either[Exception, Value]
Run Code Online (Sandbox Code Playgroud)

你可以写:

val abc: Either[Exception, Value] =
  a.flatMap { aValue =>
    b.flatMap { bValue =>
      c.map { cValue =>
        (aValue, bValue, cValue)
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

这要感谢理解,可以写得更短:

val abc = for {
  aValue <- a
  bValue <- b
  cValue <- c
} yield (aValue, bValue, cValue)
Run Code Online (Sandbox Code Playgroud)

但是,如果你使用java.lang.Exceptionas 你错误,那么使用它会更有意义,Try因为Try[A]它与 非常相似Either[Throwable, A],除了它也可以捕获它内部抛出的异常(并且编写时间更短)。