Ben Flowers Ben Flowers - 9 days ago 5
Scala Question

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

I have a sequence of Errors or Views (

Seq[Xor[Error,View]]
)

I want to map this to an Xor of the first error (if any) or a Sequence of Views
(
Xor[Error, Seq[View]]
) or possibly simply (
Xor[Seq[Error],Seq[View]
)

How can I do this?

Answer

You can use sequenceU provided by the bitraverse syntax, similar to as you would do with scalaz. It doesn't seem like the proper type classes exist for Seq though, but you can use 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)))