Проверка Scalaz и ограничения ApplicativeBuilder - PullRequest
10 голосов
/ 21 апреля 2011

Мы используем признак проверки скаляза в нашем проекте для проверки параметров HTTP.Распространенным случаем является принятие нескольких проверенных значений и выполнение необходимых действий только в том случае, если все они верны, в противном случае возвращается список ошибок:

(pavam1Val.liftFailNel |@|
 param2Val.liftFailNel |@|
 param3Val.liftFailNel) {
    getSomeResponse(_, _, _)
}

Это работает хорошо, пока нам не нужно использовать более 8 параметров, потому что| @ |оператор конструирует ApplicativeBuilder, который ограничен 8 аргументами.Есть ли другой способ выполнить такую ​​единовременную проверку, желательно, чтобы код читался?

Ответы [ 2 ]

11 голосов
/ 23 апреля 2011

вы хотите использовать метод <*> вместе с одним вызовом 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 голосов
/ 12 февраля 2012

Еще пара способов сделать это:

  1. Поднимите соответствующую функцию в контекст Validation, а затем примените ее к значениям.

    getSomeResponse.lift[({ type L[X] = Validation[Y, X] })#L] apply (
      param1Val, param2Val, param3Val
    )
    
  2. Используйте понимание монады.

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