I am using scalaz validation, and have some code to validate products.
def validateProduct(product: Option[Product]): ValidationNel[String, Product] = ???
Given a list of products, I want to get a single validation containing the whole list as a successful value or a list of validation errors. It seems like some kind of fold should do it, but I am not sure what the combination function should be.
def validateProducts(products: Seq[Option[Product]]): ValidationNel[String, Seq[Product]] = {
val listOfValidations: Seq[ValidationNel[String, Product]] = products.map(validateProduct _)
val validatedList:ValidationNel[Seq[String], Seq[Product]] = ??? // what to do here?
???
}
Any help is appreciated
If instead of a ValidationNel[List[String], List[Product]]
you want a ValidationNel[String, List[Product]]
(i.e., all the failures in the same list), you can just use traverse
:
val result: ValidationNel[String, List[Product]] =
products.toList.traverseU(validateProduct)
Note that I've converted the Seq
to a List
as there are no type class instances for raw Seq
, and I'm using traverseU
rather than traverse
as Scala's type inference doesn't quite work for non-trivial type constructors like ValidationNel
You can use fold with applicative
import scalaz.syntax.validation._
import scalaz.syntax.applicative._
case class Product(name: String)
val allGood = Seq(
Product("a").successNel[String],
Product("b").successNel[String]
)
val aggregated: ValidationNel[String, Seq[Product]] =
allGood.foldLeft(Seq.empty[Product].successNel[String]) {
case (acc , v) => (acc |@| v)(_ :+ _)
}
println(aggregated)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With