How to flatten a sequence of cats' ValidatedNel values

点点圈 提交于 2019-12-12 07:49:06

问题


I need to flatten a sequence of cats.data.ValidatedNel[E, T] values to a single ValidatedNel value:

val results: Seq[cats.data.ValidatedNel[E, T]] = ???

val flattenedResult: cats.data.ValidatedNel[E, T]

I can do it like this:

import cats.std.list._, cats.syntax.cartesian._

results.reduce(_ |@| _ map { case _ => validatedValue })

but wonder if a pre-defined library methods exists.


回答1:


It depends on how you want to combine them (what is validatedValue in your question ?)

import cats.data.{Validated, ValidatedNel}
import cats.implicits._

val validations1 = List(1.validNel[String], 2.valid, 3.valid)
val validations2 = List(1.validNel[String], "kaboom".invalidNel, "boom".invalidNel)

If you want to combine the Ts, you can use Foldable.combineAll which uses a Monoid[T] :

val valSum1 = validations1.combineAll 
// Valid(6)
val valSum2 = validations2.combineAll 
// Invalid(OneAnd(kaboom,List(boom)))

If you want to get a ValidationNel[String, List[T]], you can use Traverse.sequence :

val valList1: ValidatedNel[String, List[Int]] = validations1.sequence
// Valid(List(1, 2, 3))
val valList2: ValidatedNel[String, List[Int]] = validations2.sequence
// Invalid(OneAnd(kaboom,List(boom)))

If you don't care about the result, which seems to be the case, you can use Foldable.sequence_.

val result1: ValidatedNel[String, Unit] = validations1.sequence_
//  Valid(())
val result2: ValidatedNel[String, Unit] = validations2.sequence_
// Invalid(OneAnd(kaboom,List(boom)))

validations1.sequence_.as(validatedValue) // as(x) is equal to map(_ => x)


来源:https://stackoverflow.com/questions/37773658/how-to-flatten-a-sequence-of-cats-validatednel-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!