简体   繁体   English

如何在Scala中实现简单验证

[英]How to implement simple validation in Scala

Suppose I need to validate request parameters. 假设我需要验证请求参数。 The validation result is either Success or Failure with NonEmptyList[String] . 验证结果是使用NonEmptyList[String] SuccessFailure I can probably use ValidationNel[String, Unit] but it seems a bit overkill. 我可能可以使用ValidationNel[String, Unit]但似乎有点过大。 I guess I need a simpler abstraction (see below). 我想我需要一个更简单的抽象(请参见下文)。

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

and a binary operation andAlso to combine two results: 以及二进制运算和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) 
    } 
}

Now if I validate three parameters with functions checkA , checkB , and checkC I can easily compose them as follows: 现在,如果我使用checkAcheckBcheckC函数验证三个参数, checkB可以轻松地将它们组成如下:

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)

Does it make sense ? 是否有意义 ?
Does this abstraction have a name ? 这个抽象有名称吗? Maybe a Monoid ? 也许一个Monoid
Is it implemented in scalaz or any other scala library ? 是否在scalaz或任何其他Scala库中实现了?

It is indeed a Monoid , and you can be much more precise : it is a List[String] (up to an isomporphism). 实际上,它是一个Monoid ,您可以更加精确:它是一个List[String] (最多是同感)。 ValidationResult is indeed isomorphic to a List[String] , with Success for Nil , and andAlso is concatenation ::: / ++ . ValidationResult实际上对于List[String]是同构的,对于NilSuccess ,而andAlso是串联::: / ++

This makes sense, a ValidationResult is a list of errors, and when there are none, that means success. 这很有道理, ValidationResult是错误列表,如果没有错误,则表示成功。

However, as you note right at the beginning, it all amounts to using ValidationNel[String, Unit] , where Unit , "no data of interest" is the interesting part. 但是,正如您在一开始就注意到的那样,所有这些都相当于使用ValidationNel[String, Unit] ,其中Unit ,“无相关数据”是有趣的部分。 If means you will handle the actual data separately. 如果是,则将分别处理实际数据。 You may win a little bit here, and that little bit is avoiding the syntax of Applicative , sprinkling your code with |@| 您可能会在这里赢得一点,而那一点是避免使用Applicative的语法,在代码中加上|@| and suchlike; 像这样 also, a not-often mentioned price of Monads and Co, making it easier to work with a debugger. 同样,Monads and Co的价格不经常被提及,这使得调试器的使用变得更加容易。 But there is a downside, as your code grows with places where errors may occur multiplying too, managing the flow by hand will quickly become painful and I would not go that way. 但是有一个弊端,因为您的代码随着错误发生的地方而增长,手动管理流程将很快变得很痛苦,我不会那样做。

The usual alternative is exceptions. 通常的选择是例外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM