Scala-Cats: - Возможно ли объединить ошибки из разных NonEmptyLists? - PullRequest
0 голосов
/ 19 сентября 2018

Есть ли возможность объединить разные ошибки из нескольких переменных, используя NonEmptyList

type ValidationResult[A] = ValidatedNel[String, A]

def throwErrorsWhenNumberIsLessThan6(x:Int):ValidationResult[Int] = if(x<6) s"$x !> 6".invalidNel else (x+6).validNel

def throwErrorsWhenStringLengthIsLessThan6(x:String):ValidationResult[String] = if(x.length<6) s"$x length > 6".invalidNel else (x+" OK!!! ").validNel

val ints = Range.apply(1,10).map(throwErrorsWhenNumberIsLessThan6).toList

val strings = Range.apply(1,10).map(e => throwErrorsWhenStringLengthIsLessThan6(e.toString)).toList

Есть ли способ объединить все ошибки, доступные в ints и strings?

Предполагая , что ints и strings будут содержать один и тот же тип данных в NonEmptyList.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Да, для этого вы можете использовать методы из класса типов Applicative.

Например, теперь ваш ints имеет тип List[ValidationResult[Int]].Вы можете использовать метод sequence, чтобы преобразовать его в ValidationResult[List[Int]]:

import cats.implicits._

scala> val validatedInts = ints.sequence

validatedInts: ValidationResult[List[Int]] =
  Invalid(NonEmptyList(1 !> 6, 2 !> 6, 3 !> 6, 4 !> 6, 5 !> 6))

Или вы можете использовать traverse вместо map при создании объекта ints для получения ValidationResult немедленно:

scala> val validatedInts2 = (1 until 10).toList.traverse(throwErrorsWhenNumberIsLessThan6)

validatedInts2: ValidationResult[List[Int]] = 
  Invalid(NonEmptyList(1 !> 6, 2 !> 6, 3 !> 6, 4 !> 6, 5 !> 6))

И сделайте то же самое для strings:

scala> val validatedStrings = (0 until 2).toList.traverse(e =>
  throwErrorsWhenStringLengthIsLessThan6(e.toString + "KK")).toList

validatedStrings: ValidationResult[List[String]] = 
  Invalid(NonEmptyList(0KK length > 6, 1KK length > 6))

И теперь вы можете объединить validatedInts и validatedStrings в один ValidationResult сmapN или tupled методы:

scala> (validatedInts, validatedStrings).tupled
res0: ValidationResult[(List[Int], List[String])] = 
  Invalid(NonEmptyList(1 !> 6, 2 !> 6, 3 !> 6, 4 !> 6, 5 !> 6, 0KK length > 6, 1KK length > 6))

scala> (validatedInts, validatedStrings).mapN(_.map(_.toString) ++ _)
res1: ValidationResult[List[String]] = 
  Invalid(NonEmptyList(1 !> 6, 2 !> 6, 3 !> 6, 4 !> 6, 5 !> 6, 0KK length > 6, 1KK length > 6))
0 голосов
/ 19 сентября 2018

Это сработало для меня

type ValidationResult[A] = ValidatedNel[String, A]
def throwErrorsWhenNumberIsLessThan6(x:Int):ValidationResult[Int] = if(x<6) s"$x !> 6".invalidNel else (x+6).validNel
def throwErrorsWhenStringLengthIsLessThan6(x:String):ValidationResult[String] = if(x.length<6) s"$x length > 6".invalidNel else (x+" OK!!! ").validNel

val ints = Range.apply(0,2).map(throwErrorsWhenNumberIsLessThan6).toList
val strings = Range.apply(0,2).map(e => throwErrorsWhenStringLengthIsLessThan6(e.toString+"KK")).toList

ints.filter(_.isInvalid).:::(strings.filter(_.isInvalid))
//List(Invalid(NonEmptyList(0KK length > 6)), Invalid(NonEmptyList(1KK length > 6)), Invalid(NonEmptyList(0 !> 6)), Invalid(NonEmptyList(1 !> 6)))
...