簡體   English   中英

映射並縮小/折疊scalaz.Validation的HList

[英]Map and reduce/fold over HList of scalaz.Validation

我開始時有這樣的事情:

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但最后一行將停止工作,我不得不放棄一些靜態安全。 所以我看向無形:

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上尋求過幫助,但似乎並不是人們只有開箱即用的答案。 但是,我真的很想學習如何在實際和學習目的上解決這個問題。

PS實際上我的驗證包含在Kleisli[Va, A, B]因此我可以使用>=>組成單獨的驗證步驟,但這似乎與問題正交,因為.map(...)是達到之后,所有Kleisli都將“減少”到Validation[String, A]

以下是shapeless-contribtraverse

import scalaz._, Scalaz._
import shapeless._, contrib.scalaz._, syntax.std.tuple._

def nonEmpty[A] = (msg: String) => (a: Option[A]) => a.toSuccess(msg)

val postal: Option[String] = Some("00000")
val country: Option[String] = Some("us")

val params = (
  postal  |> nonEmpty[String]("no postal"),
  country |> nonEmpty[String]("no country")
)

接着:

object ToVNS extends Poly1 {
  implicit def validation[T] = at[Validation[String, T]](_.toValidationNel)
}

val result = traverse(params.productElements)(ToVNS).map(_.tupled)

現在result是一個ValidationNel[String, (String, String)] ,你可以用它來做任何事情,你可以通過使用|@|減少你可以得到的糟糕的ApplicativeBuilder |@|

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM