在Scala中编写验证函数

时间:2015-05-29 10:54:54

标签: 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) 

有意义吗?

1 个答案:

答案 0 :(得分:1)

当左手类型是半群时,您可以编写验证。您的列表有效,但scalaz提供了内置的select switchID, patchCordID from switch where patchCordID in (select distinct patchCordID from switch where switchID=197) ,您应该使用它。有一些便利函数,如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 }
    }
  }