Liste von scalaz.Validation kartieren und verkleinern / überklappen
Ich habe mit so etwas angefangen:
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) => ... }
Nun dachte ich, es wäre schön, das Boilerplate zu verkleinern, um die Lesbarkeit zu verbessern und um nicht mehr Junior-Teammitgliedern erklären zu müssen, was.toValidateNel
und|@|
bedeuten. Der erste Gedanke warList
aber dann würde die letzte Zeile nicht mehr funktionieren und ich müsste auf statische Sicherheit verzichten. Also schaute ich zu 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(_ |@| _)
jedoch, ich kann nicht einmal scheinen, an dem @ vorbei zu komm.map(...)
bisschen. Ich habe nach einem Vorschlag auf #scalaz versucht:
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 })
...umsonst
Ich habe bei #scalaz um Hilfe gebeten, aber es scheint nicht so, als hätten die Leute eine Out-of-the-Box-Antwort auf diese Frage. Ich bin jedoch sehr daran interessiert zu lernen, wie dies sowohl für praktische als auch für Lernzwecke gelöst werden kann.
P.S. In Wirklichkeit sind meine Validierungen in @ verpackKleisli[Va, A, B]
, damit ich mit @ einzelne Validierungsschritte zusammenstellen ka>=>
aber das scheint orthogonal zum Thema zu sein, als zu dem Zeitpunkt, dass.map(...)
ist erreicht, alleKleisli
s wird auf @ "reduziert&quoValidation[String, A]
.