【问题标题】:How to implement simple validation in Scala如何在 Scala 中实现简单的验证
【发布时间】:2015-03-08 09:36:58
【问题描述】:

假设我需要验证请求参数。验证结果是SuccessFailureNonEmptyList[String]。我可能可以使用ValidationNel[String, Unit],但这似乎有点矫枉过正。我想我需要一个更简单的抽象(见下文)。

trait ValidationResult
object Success extends ValidationResult
class Failure(errors: NonEmptyList[String]) extends ValidationResult

和一个二元运算andAlso组合两个结果:

trait ValidationResult {
  def andAlso(other: ValidationResult): ValidationResult = 
    (this, other) match {
      case (Success, Success) => Success
      case (Success, failure @ Failure(_)) => failure
      case (failure @ Failure(_), Success) => failure
      case (Failure(errors1), Failure(errors2)) => Failure(errors1 + errors2) 
    } 
}

现在,如果我使用函数 checkAcheckBcheckC 验证三个参数,我可以轻松地将它们组合如下:

def checkA(a: A): ValidationResult = ...
def checkB(b: B): ValidationResult = ...
def checkC(c: C): ValidationResult = ...
def checkABC(a: A, b: B, c: C) = checkA(a) andAlso checkB(b) andAlso checkC(c)

这有意义吗?
这个抽象有名字吗?也许是Monoid
它是在 scalaz 或任何其他 scala 库中实现的吗?

【问题讨论】:

    标签: validation scala scalaz


    【解决方案1】:

    它确实是一个Monoid,你可以更准确地说:它是一个List[String](最多同态)。 ValidationResult 确实与List[String] 同构,Success 代表Nil,而andAlso 是串联::: / ++

    这是有道理的,ValidationResult 是一个错误列表,如果没有,则表示成功。

    但是,正如您在开头所指出的那样,这一切都相当于使用ValidationNel[String, Unit],其中Unit,“没有感兴趣的数据”是有趣的部分。如果意味着您将分别处理实际数据。你可能会在这里赢一点,那一点就是避免使用Applicative 的语法,在你的代码中添加|@| 之类的东西;此外,Monads 和 Co 的不经常提到的价格,使得使用调试器更容易。但是有一个缺点,随着代码的增长,错误可能会成倍增加,手动管理流程很快就会变得很痛苦,我不会那样做。

    通常的选择是例外。

    【讨论】:

    • 谢谢。我将尝试继续使用 monoid,因为我现在需要它来验证我的测试中的输出。
    猜你喜欢
    • 2016-04-25
    • 2019-02-22
    • 2021-11-15
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多