Проверка проверки Scalaz: преобразование последовательности валидаций в одну проверку
Я использую проверку валидации, и имею некоторый код для проверки продуктов.
def validateProduct(product: Option[Product]): ValidationNel[String, Product] = ???
Учитывая список продуктов, я хочу получить одну проверку, содержащую весь список, как успешное значение или список ошибок проверки. Кажется, что какой-то склад должен делать это, но я не уверен, какая функция комбинации должна быть.
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?
???
}
Любая помощь приветствуется
Ответы
Ответ 1
Если вместо ValidationNel[List[String], List[Product]]
вам нужен ValidationNel[String, List[Product]]
(т.е. все сбои в том же списке), вы можете просто использовать traverse
:
val result: ValidationNel[String, List[Product]] =
products.toList.traverseU(validateProduct)
Обратите внимание, что я преобразовал Seq
в List
, поскольку нет экземпляров класса типа для raw Seq
, и я использую traverseU
, а не traverse
как Scala вывод типа не работает для нетривиальных конструкторов типа ValidationNel
Ответ 2
Вы можете использовать fold с аппликативным
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)