Как вернуть право любого - PullRequest
       0

Как вернуть право любого

0 голосов
/ 18 февраля 2020

У меня есть значение этого типа:

List[Either[Error, Files]]

, и у меня есть функция, которая проверяет, есть ли какие-либо ошибки, подобные этой:

  private def process(result: List[Either[Error, Files]]): Either[Error, List[Files]] = {
    if(result.exists(p => p.isLeft)){
      Left(Error("some downloads failed"))
    }else{
      Right(
      Right(
        result.collect {
          case Right(value) => value
        }
      )

    }

  }

Это лучший способ вернуть список файлов, если в результате нет ошибок?

Ответы [ 3 ]

4 голосов
/ 18 февраля 2020

Существует библиотека cats, у которой есть sequence метод расширения для этой вещи https://gist.github.com/gbersac/14114f8bf8d0b1c6ea455aacdee0fcd8.

2 голосов
/ 18 февраля 2020

Вот решение, которое использует partition:

private def process(result: List[Either[Error, Files]]): Either[Error, List[Files]] =
  result.partition(_.isLeft) match {
    case (Left(error)::_, _) =>
      Left(error)
    case (_, r) =>
      Right(r.collect{ case Right(r) => r })
  }

Эта рекурсивная версия более эффективна, но, возможно, менее ясна:

private def process(result: List[Either[Error, Files]]): Either[Error, List[Files]] = {
  @annotation.tailrec
  def loop(rem: List[Either[Error, Files]], res: List[Files]): Either[Error, List[Files]] =
    rem match {
      case Left(error) :: _ =>
        Left(error)
      case Right(file) :: tail =>
        loop(tail, file +: res)
      case _ =>
        Right(res.reverse)
    }

  loop(result, Nil)
}
0 голосов
/ 18 февраля 2020

В этом случае вы можете использовать foldLeft для сбора всех ошибок или всех файлов. Я не знаю, как выглядит Error, но предположим, что это простой класс case со строкой сообщения внутри:

case class Error(message: String) {
  def append(message: Error): Error = copy(message = message + s"; ${message.message}")
}

def process(result: List[Either[Error, Files]]): Either[Error, List[Files]] = {
  val init: Either[Error, List[Files]] = Right(Nil)
  result.foldLeft(init) {
    case (Left(allErrors), Left(currentError)) => Left(allErrors.append(currentError))
    case (Left(allErrors), Right(_)) => Left(allErrors)
    case (Right(_), Left(currentError)) => Left(currentError)
    case (Right(allFiles), Right(currentFile)) => Right(currentFile :: allFiles)
  }
}

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...