Mapeie e reduza / dobre a HList do scalaz.Validation
Comecei com algo assim:
def nonEmpty[A] = (msg: String) => (a: Option[A]) => a.toSuccess(msg)
val postal: Option[String] = request.param("postal")
val country: Option[String] = request.param("country")
val params =
(postal |> nonEmpty[String]("no postal" )).toValidationNel |@|
(country |> nonEmpty[String]("no country")).toValidationNel
params { (postal, country) => ... }
Agora pensei que seria bom reduzir o padrão para melhor legibilidade e não precisar explicar aos membros mais jovens da equipe o que.toValidateNel
e|@|
significar. O primeiro pensamento foiList
mas então a última linha deixaria de funcionar e eu teria que desistir de alguma segurança estática. Então olhei para Shapeless:
import shapeless._; import poly._; import syntax.std.tuple._
val params = (
postal |> nonEmpty[String]("no postal"),
country |> nonEmpty[String]("no country")
)
params.map(_.toValidatioNel).reduce(_ |@| _)
no entanto, eu não consigo nem passar do.map(...)
mordeu. Tentei de acordo com uma sugestão no #scalaz:
type Va[+A] = Validation[String, A]
type VaNel[+A] = ValidationNel[String, A]
params.map(new (Va ~> VaNel) { def apply[T](x: Va[T]) = x.toValidationNel })
...para nenhum proveito.
Pedi ajuda no #scalaz, mas não parece algo para o qual as pessoas tenham uma resposta imediata. No entanto, estou realmente interessado em aprender como resolver isso tanto para fins práticos quanto para aprendizado.
P.S. na realidade, minhas validações estão envolvidasKleisli[Va, A, B]
para que eu pudesse compor etapas de validação individuais usando>=>
mas isso parece ser ortogonal ao problema, pois no momento em que.map(...)
é atingido, tudoKleisli
s foram "reduzidos" paraValidation[String, A]
.