Scala:将整个列表中的每个元素与每个元素中的每个元素组合 [英] Scala: Combine Either per the whole List with Either per elements

查看:454
本文介绍了Scala:将整个列表中的每个元素与每个元素中的每个元素组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Either列表,表示错误:

I have a list of Either, which represents error:

type ErrorType = List[String]
type FailFast[A] = Either[ErrorType, A]

import cats.syntax.either._
val l = List(1.asRight[ErrorType], 5.asRight[ErrorType])

如果它们都正确,我想获得[A]的列表,在这种情况下-List[Int]

If all of them are right, I want to get a list of [A], in this case - List[Int]

如果剩下任何Either,我想合并所有两个的所有错误并将其返回.

If any Either is left, I want to combine all errors of all either and return it.

我在[如何将Seq [Either [A,B]]简化为Either [A,Seq [B]]

但是很久以前.例如,答案之一提供了使用partitionMap的能力,目前我找不到.可能有一个更好,更优雅的解决方案.斯卡拉猫的例子很好.

But it was quite long ago. For instance, one of the answers offers to use partitionMap, which I cannot find at this moment. Probably there is a better, more elegant solution. Example with scala-cats would be great.

我想如何使用它:

for {
  listWithEihers <- someFunction
  //if this list contains one or more errors, return Left[List[String]]
  //if everything is fine, convert it to:
  correctItems <- //returns list of List[Int] as right
} yield correctItems

此理解的返回类型必须为:

Return type of this for-comprehension must be:

Either[List[String], List[Int]]

推荐答案

正如注释中已经提到的,Either对于快速失败行为很有用.为了积累多个错误,您可能需要类似Validated的东西.而且:

As already mentioned in the comments, Either is good for fail-fast behavior. For accumulating multiple errors, you probably want something like Validated. Moreover:

  • 列表是可遍历的(具有Traverse的实例)
  • 已验证是适用的
  • Validated.fromEitherEither[List[String], X]映射到Validated[List[String], X],这正是traverse中的功能所需要的.
  • List is traversable (has instance of Traverse)
  • Validated is applicative
  • Validated.fromEither maps Either[List[String], X] to Validated[List[String], X], that's exactly what you need as function in traverse.

因此,您可以尝试:

  • l.traverse(Validated.fromEither)(如果您对Validated
  • 没问题)
  • l.traverse(Validated.fromEither).toEither,如果您真的想要最后一个Either.
  • l.traverse(Validated.fromEither) if you are OK with a Validated
  • l.traverse(Validated.fromEither).toEither if you really want an Either in the end.

包含所有导入的完整示例:

Full example with all imports:

import cats.data.Validated
import cats.syntax.validated._
import cats.syntax.either._
import cats.syntax.traverse._
import cats.instances.list._
import cats.Traverse
import scala.util.Either

type ErrorType = List[String]
type FailFast[A] = Either[ErrorType, A]
val l: List[Either[ErrorType, Int]] = List(1.asRight[ErrorType], 5.asRight[ErrorType])

// solution if you want to keep a `Validated`
val validatedList: Validated[ErrorType, List[Int]] =
  l.traverse(Validated.fromEither)

// solution if you want to transform it back to `Either`
val eitherList: Either[ErrorType, List[Int]] =    
  l.traverse(Validated.fromEither).toEither

这篇关于Scala:将整个列表中的每个元素与每个元素中的每个元素组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆