4

我有一系列错误或视图 ( Seq[Xor[Error,View]])

我想将其映射到第一个错误(如果有)的 Xor 或视图序列 ( Xor[Error, Seq[View]]) 或可能只是 ( Xor[Seq[Error],Seq[View])

我怎样才能做到这一点?

4

2 回答 2

7

您可以使用sequenceU提供的bitraverse语法,类似于使用 scalaz。虽然似乎不存在正确的类型类Seq,但您可以使用List.

import cats._, data._, implicits._, syntax.bitraverse._

case class Error(msg: String)

case class View(content: String)

val errors: List[Xor[Error, View]] = List(
  Xor.Right(View("abc")), Xor.Left(Error("error!")), 
  Xor.Right(View("xyz"))
)

val successes: List[Xor[Error, View]] = List(
  Xor.Right(View("abc")),
  Xor.Right(View("xyz"))
)

scala> errors.sequenceU
res1: cats.data.Xor[Error,List[View]] = Left(Error(error!))

scala> successes.sequenceU
res2: cats.data.Xor[Error,List[View]] = Right(List(View(abc), View(xyz)))
于 2016-11-02T00:43:20.890 回答
4

在最新版本的 CatsXor中被删除,现在使用标准的 ScalaEither数据类型。

Michael Zajac 正确地表明您可以使用sequenceor sequenceU(实际上是在Traversenot上定义的Bitraverse)来获得Either[Error, List[View]].

import cats.implicits._

val xs: List[Either[Error, View]] = ???

val errorOrViews: Either[Error, List[View]] = xs.sequenceU

您可能想查看traverse(类似于 amap和 a sequence),您可以在大多数情况下使用它而不是sequence.

如果您想要所有失败的错误,则不能使用Either,但可以使用Validated( 或ValidatedNel,这只是Validated[NonEmptyList[A], B].

import cats.data.{NonEmptyList, ValidatedNel}

val errorsOrViews: ValidatedNel[Error, List[View]] = xs.traverseU(_.toValidatedNel)

val errorsOrViews2: Either[NonEmptyList[Error], List[View]] = errorsOrViews.toEither

您还可以使用以下方法获取错误视图MonadCombine.separate

val errorsAndViews: (List[Error], List[View]) = xs.separate

您可以在 Cats 网站上找到更多示例和信息EitherValidated

于 2016-12-01T15:34:19.290 回答