【发布时间】:2014-10-16 17:09:14
【问题描述】:
我是这样开始的:
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) => ... }
现在我认为最好减少样板文件以提高可读性,并且不必向更多初级团队成员解释.toValidateNel 和|@| 的含义。第一个想法是List,但最后一行将停止工作,我不得不放弃一些静态安全。于是我看向了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(_ |@| _)
但是,我什至无法超越 .map(...) 位。我已经按照关于#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 })
...无济于事。
我已就#scalaz 寻求帮助,但人们似乎没有开箱即用的答案。但是,我真的很想学习如何解决这个问题,既实用又实用。
附言实际上,我的验证被包裹在Kleisli[Va, A, B] 中,这样我就可以使用>=> 编写单独的验证步骤,但这似乎与问题正交,因为当到达.map(...) 时,所有Kleislis 都将是“减少”为Validation[String, A]。
【问题讨论】:
-
您肯定需要将
Poly1定义为一个对象(出于各种与稳定标识符有关的古怪的Scala 相关原因)。这看起来很像遍历,而 shapeless-contrib 的traverse可以让您一步完成toValidationNel和reduce(_ |@| _)(道德等价物)。 -
另见我模糊相关的博文here。
标签: scala validation scalaz shapeless scalaz7