猫 Seq[Xor[A,B]] => Xor[A, Seq[B]]

4

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

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

我该如何做?


那种类型方法的函数名为“sequence”,它是“遍历”的特殊情况。我认为你需要提供一种将Xor隐式转换为Traverse的方法。https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/Traverse.scala - A Spoty Spot
2个回答

6

您可以使用bitraverse语法提供的sequenceU,就像您在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)))

4
在最近的 Cats 版本中,Xor 已被移除,现在使用标准的 Scala Either 数据类型。Michael Zajac 正确地展示了如何使用 sequencesequenceU(实际上这两个函数都是定义在 Traverse 而不是 Bitraverse 上),可以得到一个 Either[Error, List[View]]
import cats.implicits._

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

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

你可能需要查看 traverse(类似于 mapsequence 的组合),你可以在大多数情况下使用它来代替 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的示例和信息。


当前 Cats 版本更新: xs.sequenceU 现在已经改为 xs.sequence; trverseU 已经更名为 traverse. - Sasha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接