如何使用applicative functor结合Scalaz验证

时间:2013-06-04 13:21:10

标签: validation scala scalaz scalaz7

无法弄清楚是否可以使用Scalaz 7编写类似的内容。我试图用代码块中的注释表达自己。

def validate1(p: String) = ValidationNel[String, Value] = ...
def validate2(p: String) = ValidationNel[String, Value] = ...

validateCombination(p1: String, p2: String) = {
  // I would like to write something like
  (validate1(p1) |@| validate2(p2)) { (v1, v1) =>
    // And validate the combinations here and return successNel of failNel
  }
}

def validate(p1: String, p2: String, p3: String) = {
  (validateCombination(p1, p2) |@| validate1(p3)) { (v1, v2, v3) =>
    // Notice the three parameters I want to have here
  }
}

我最终在validateCombinations中遇到了不同类型的令人困惑的编译错误,或者只有2个参数用于我在验证函数中的应用函数,其中一个是ValidationNel [...]类型。

1 个答案:

答案 0 :(得分:6)

您可以在方法.flatMap(identity)中使用validateCombination在方法ValidationNel[String, (Value, Value)]中生成pattern matchingvalidate,如下所示:

def validateCombination(p1: String, p2: String): ValidationNel[String, (Value, Value)] = {
  // I would like to write something like
  (validate1(p1) |@| validate2(p2)) { (v1, v1) =>
    (v1, v2).successNel[String]
  }.flatMap(identity)
}

def validate(p1: String, p2: String, p3: String) = {
  (validateCombination(p1, p2) |@| validate1(p3)) { case ((v1, v2), v3) =>
    // Notice the three parameters I want to have here
  }
}

<强> flatMap(同一性)

通常,您会在嵌套容器上使用方法flattenM[T]获取M[M[T]]。它适用于FutureOptionTry,集合等。

在这种情况下type M[T] = ValidationNel[String, T]

我不知道为什么flatten中没有方法Validation,但您始终可以使用flatMap(identity)代替flatten

<强>匹配

作为Ben James notedflatMap上的Validation是可疑的。您可以随时使用match代替它:

(validate1(p1) |@| validate2(p2)) { (v1, v1) =>
  (v1, v2).successNel[String]
} match {
  case Success(s) => s
  case Failure(f) => Failure(f)
}

模式匹配

模式匹配是处理元组的常用方法。例如,它与foldLeft方法一样有用,例如foldLeft(1 -> 2){ case ((a, b), c) => ??? }

如果您发现自己在_N上使用getter Tuple,则可能应该使用模式匹配。

理解

由于Daniel C. Sobral noted的理解力可能更容易理解。

您可以在validate方法中使用它,如下所示:

def validate(p1: String, p2: String, p3: String) = {
  for{
    (v1, v2) <- validateCombination(p1, p2) // pattern matching
    v3 <- validate1(p3)
  } yield ??? // Your code here
}

它涉及没有case关键字的模式匹配。

请注意,对于flatMap上的理解调用validateCombination(p1, p2),如果validate1(p3)validateCombination(p1, p2),您将从Failure丢失错误消息。相反,|@|收集来自双方的所有错误消息。