Как проверить ошибки в scala чисто функционально? - PullRequest
0 голосов
/ 26 апреля 2020

Есть ли способ избежать вложения в приведенном ниже коде при проверке ошибок без простого объединения функций?

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
                                        }
                     }
   }
}

Ответы [ 2 ]

5 голосов
/ 26 апреля 2020

Во-первых: по соглашению (импортировано из Haskell, где это имело смысл) ошибки равны Left, а правильные значения Right.

Как только мы установим sh это соглашение: .map позволяет отображать правильное значение (оно оставляет значение Left нетронутым), в то время как .flatMap позволяет превратить значение Right в Left или Right - при Right оно продолжит композицию, а Left будет разорвать цепь.

Имея:

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

вы можете написать:

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

, что благодаря пониманию может быть записано короче как:

val abc = for {
  aValue <- a
  bValue <- b
  cValue <- c
} yield (aValue, bValue, cValue)

Однако, если вы используете java.lang.Exception в качестве ошибки, то имеет смысл использовать Try, потому что Try[A] очень похож на Either[Throwable, A], за исключением того, что он также может перехватывать исключения, возникающие внутри него. (и короче, чтобы написать).

2 голосов
/ 26 апреля 2020

Поскольку a, b и c не зависят друг от друга Applicative подход также может избежать "пирамиды гибели"

import cats.implicits._
(a, b, c).mapN(_ + _ + _)

из, если вы хотите sh, чтобы оставить счастливое значение на левой стороне, подумайте о том, чтобы поменять стороны, как показано ниже

import cats.implicits._
(a.swap, b.swap, c.swap).mapN(_ + _ + _).swap
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...