Scala:将整个列表中的每个元素与每个元素中的每个元素组合 [英] Scala: Combine Either per the whole List with Either per elements
问题描述
我有一个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.fromEither
将Either[List[String], X]
映射到Validated[List[String], X]
,这正是traverse
中的功能所需要的.
- List is traversable (has instance of
Traverse
) - Validated is applicative
Validated.fromEither
mapsEither[List[String], X]
toValidated[List[String], X]
, that's exactly what you need as function intraverse
.
因此,您可以尝试:
-
l.traverse(Validated.fromEither)
(如果您对Validated
没问题)
-
l.traverse(Validated.fromEither).toEither
,如果您真的想要最后一个Either
.
l.traverse(Validated.fromEither)
if you are OK with aValidated
l.traverse(Validated.fromEither).toEither
if you really want anEither
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屋!