Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Scala编写验证函数_Scala_Validation_Scalaz - Fatal编程技术网

用Scala编写验证函数

用Scala编写验证函数,scala,validation,scalaz,Scala,Validation,Scalaz,假设我需要编写一个验证函数Validate[a]: type Status[A] = Validation[List[String], A] type Validate[A] = A => Status[A] // should be Kleisli 如果输入有效,则函数返回带有输入的成功;如果输入无效,则返回带有错误列表的失败 比如说, val isPositive: Validate[Int] = {x: Int => if (x > 0) x.success els

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

type Status[A] = Validation[List[String], A]
type Validate[A] = A => Status[A] // should be Kleisli
如果输入有效,则函数返回带有输入的
成功
;如果输入无效,则返回带有错误列表的
失败

比如说,

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提供了一个内置的
类型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
作为
验证的缩写)形式的新单个函数的组合

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

我已经设法写了这篇作文,但我觉得可能有更好的方法

  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 }
  }
}

是的,我想知道如何组合返回验证的函数。我认为,由于这些函数是
Kleisli
,我们可以将它们完全组合为
Validation
值。这就是我问这个问题的原因。@Michael,我刚刚写了一个。我相信还有更好的方法,因为我的
Validate
Kleisli
(我已经更新了问题),所以我可以免费得到这样一篇作文。@Michael我同意,我想你可以,但我想不出来好吧,现在我觉得我应该去REPL,试着将解决方案编码为real,而不是询问:)验证只形成一个半群,其中左半群和右半群都需要提醒。我认为
Validation[E,A]
要求
E
是一个半群,但它可能不是。它要求
E:semigroup
形成一个应用程序,它要求
E:semigroup,A:semigroup
形成一个半群。看不到重复,但有点相关,可能导致不同的方法:
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 }
  }
}