如何同时使用析取和验证?

How to use both Disjunction and Validation?

假设我需要使用下面列出的函数创建 A 的实例:

case class A(x: X, y: Y, z: Z)

val makeX: String => Error \/ X = ???
val makeY: String => Error \/ Y = ???
val makeZ: String => Error \/ Z = ???

val makeA: (String, String, String) => NonEmptyList[Error] \/ A = ???

因为我想累积 makeXmakeYmakeZ 的错误,所以我使用 scalaz.Validation:

val makeA: (String, String, String) => NonEmptyList[Error] \/ A = (s1, s2, s3) => {
  val x = makeX(s1).validation.toValidationNel
  val y = makeY(s2).validation.toValidationNel
  val z = makeZ(s3).validation.toValidationNel
  val a = (x |@| y |@| z)(A.apply _)
  a.disjunction
}

不幸的是.validation.toValidationNel看起来有点尴尬。您将如何改进此代码?

有辅助函数:

def vnel[A](a: Error \/ A) = a.validation.toValidationNel

您现在可以:

val makeA = (s1:String, s2:String, s3:String) => 
  (vnel(makeX(s1)) |@| vnel(makeY(s2)) |@| vnel(makeZ(s3)))(A.apply).disjunction