Ограничения проверки Scalaz и ApplicativeBuilder
Мы используем свойство валидации scalaz в нашем проекте для проверки параметров HTTP. Обычный случай принимает несколько подтвержденных значений и выполняет необходимые действия только в том случае, если все они действительны, возвращая список ошибок в противном случае:
(pavam1Val.liftFailNel |@|
param2Val.liftFailNel |@|
param3Val.liftFailNel) {
getSomeResponse(_, _, _)
}
Это работает хорошо, пока мы не будем использовать более 8 параметров, потому что | @| оператор-конструктор ApplicativeBuilder, который ограничен 8 аргументами. Есть ли другой способ выполнить такую проверку "все в один раз", предпочтительно, чтобы код читался?
Ответы
Ответ 1
вы хотите использовать метод <*>
, а также один вызов map
(или ∘
, если хотите). Вы можете продолжать использовать <*>
неопределенно.
scala> val param1Val = success[String, Int](7)
param1Val: scalaz.Validation[String,Int] = Success(7)
scala> val param2Val = failure[String, Int]("abc")
param2Val: scalaz.Validation[String,Int] = Failure(abc)
scala> val param3Val = success[String, Int](9)
param3Val: scalaz.Validation[String,Int] = Success(9)
scala> val r = param1Val <*> (param2Val <*> (param3Val map getSomeResponse))
r: scalaz.Validation[String,Int] = Failure(abc)
Ответ 2
Еще несколько способов сделать это:
-
Поднимите соответствующую функцию в контекст Validation
, а затем примените ее к значениям.
getSomeResponse.lift[({ type L[X] = Validation[Y, X] })#L] apply (
param1Val, param2Val, param3Val
)
-
Используйте понимание монады.
for {
x1 <- param1Val
x2 <- param2Val
x3 <- param3Val
} yield getSomeResponse(x1, x2, x3)