Подтвердить что ты не робот

Проверка проверки 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?
    ???
  }

Любая помощь приветствуется

4b9b3361

Ответ 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)