[英]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]
Success
或Failure
。 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: 现在,如果我使用checkA
, checkB
和checkC
函数验证三个参数, 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]
是同构的,对于Nil
为Success
,而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.