scala - 在 Scala 中编写验证函数

标签 scala validation scalaz

假设我需要编写一个验证函数 Validate[A] :

type Status[A] = Validation[List[String], A]
type Validate[A] = A => Status[A] // should be Kleisli

该函数返回 Success如果输入有效,则使用输入或 Failure如果不是,则带有错误列表。

例如,
val isPositive: Validate[Int] = {x: Int =>
  if (x > 0) x.success else List(s"$x is not positive").failure 
}

val isEven: Validate[Int] = {x: Int =>
  if (x % 2 == 0) x.success else List(s"$x is not even").failure
}

Validation是半群Validate也是半群并且(如果我将其定义为 Kleisli )我可以按如下方式组合验证函数:
val isEvenPositive = isEven |+| isPositive

现在假设我需要验证 X :
case class X(x1: Int, // should be positive 
             x2: Int) // should be even

Validation是一个应用仿函数 Validate也是一个应用仿函数。
val x: Validate[X] = (isPositive |@| isEven)(X.apply) 

是否有意义 ?

最佳答案

当左手类型是半群时,您可以编写验证。您的列表有效,但 scalaz 提供了一个内置的 type ValidationNel[L, R] = Validation[NonEmptyList[L], R]你应该使用它。有几个方便的功能,如 aValidation.toValidationNel用于提升具有单个错误的值。组合验证的左侧将累积所有失败,或右侧将成功应用于您的功能

def foo: ValidationNel[String, Int]
def bar: ValidationNel[String, Double]
val composed: ValidationNel[String, Double] = foo(input) |@| bar(input) apply { (i: Int, d: Double) => i * d }

如果您正在寻找以 ( V 作为 Validation 的简写形式) 形式的新单个函数的组合
(A => V[L, B], A => V[L, C]) => (A => V[L, (B, C)])

然后我不太确定正确的方法。感觉应该有一两个组合器可以做到这一点,但我还没有找到。

我已经设法写了这篇作文,但我觉得可能有更好的方法。
  def composeV[A, B, C, L: Semigroup](f: A => Validation[L, B], g: A => Validation[L, C]): A => Validation[L, (B, C)] = {
    import scalaz.syntax.arrow._
    import scalaz.syntax.apply._
    import scalaz.std.function.function1Instance
    val oneInput: (A) => (Validation[L, B], Validation[L, C]) = f &&& g
    oneInput andThen {
      case (vb, vc) =>
        vb |@| vc apply { case x: (B, C) => x }
    }
  }

这是另一种方式:
def composeV[A, B, C, L: Semigroup](f: A => Validation[L, B], g: A => Validation[L, C]): A => Validation[L, (B, C)] = {
  import scalaz.syntax.apply._
  import scalaz.std.function.function1Instance
  f |@| g apply { case (vb, vc) =>
    vb |@| vc apply { case x: (B, C) => x }
  }
}

关于scala - 在 Scala 中编写验证函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30527740/

相关文章:

scala - 使用 deb 文件和 SBT 为生产设置日志记录/配置

scala - Akka Actor 失败时重试

c++ - 尝试使用 while 语句来验证用户输入 C++

javascript - 即使在验证函数返回 false 后表单仍在提交

scala - Scala 中的 List[Try[T]] 到 Try[List[T]]

scala - Kleisli Arrow with Writer in Scala。为什么不编译?

sockets - Akka IO.TCP 与 Json

scala - 列表中的前 n 个项目(包括重复项)

javascript - 如果元素被隐藏,则忽略 .NET 验证器(显示 : none)

scala - 使用 Scalaz 比较两个 UUID ===