We're using scalaz validation trait in our project to validate HTTP parameters. The common case is taking few validated values and performing neccessary action only if all of them are valid, returning list of errors otherwise:
(pavam1Val.liftFailNel |@|
param2Val.liftFailNel |@|
param3Val.liftFailNel) {
getSomeResponse(_, _, _)
}
This works nice, until we have to use more than 8 parameters, because |@| operator constructs ApplicativeBuilder, which is limited to 8 arguments. Is there another way to perform such all-at-once validation, preferably keeping the code readable?
you want to use the <*>
method, along with a single call to map
(or ∘
if you prefer). You can keep using <*>
indefinitely.
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)
A couple more ways to do it:
Lift the relevant function to Validation
context, and then apply it to the values.
getSomeResponse.lift[({ type L[X] = Validation[Y, X] })#L] apply (
param1Val, param2Val, param3Val
)
Use monad comprehension.
for {
x1 <- param1Val
x2 <- param2Val
x3 <- param3Val
} yield getSomeResponse(x1, x2, x3)
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