开发者

Scalaz validation and ApplicativeBuilder limits

We're using scalaz validation trait in our project to validate HTTP parameters. The common case is taking few validate开发者_开发问答d 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:

  1. 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
    )
    
  2. Use monad comprehension.

    for {
      x1 <- param1Val
      x2 <- param2Val
      x3 <- param3Val
    } yield getSomeResponse(x1, x2, x3)
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜