cdm*_*kay 6 validation scala scalaz scalaz7
我正在尝试在我的应用中使用Scalaz 7验证.但是,我遇到一个问题,让|@|应用程序仿函数合并我的失败.这是我的代码:
type ValidationResult = ValidationNel[String, Unit]
def validate[A: ClassTag](instance: A, fieldNames: Option[Seq[String]] = None): ValidationResult = {
val fields = classTag[A].runtimeClass.getDeclaredFields
val fieldSubset = fieldNames match {
case Some(names) => fields.filter { field => names.contains(field.getName) }
case None => fields
}
fieldSubset.map {
field => field.getAnnotations.toSeq.map {
field.setAccessible(true)
val (name, value) = (field.getName, field.get(instance))
field.setAccessible(false)
annotation => annotation match {
case min: Min => minValidate(name, value, min.value())
case size: Size => sizeValidate(name, value, size.min(), size.max())
}
}
}.flatten[ValidationResult].foldLeft(().successNel[String])(_ |@| _)
}
Run Code Online (Sandbox Code Playgroud)
在minValidate和sizeValidate函数只是返回ValidationResults.
问题是,这段代码不会编译.错误消息是:
Type mismatch, expected F0.type#M[NotInferedB], actual: ValidationResult
Run Code Online (Sandbox Code Playgroud)
我不知道这意味着什么......我需要给Scala更多的类型信息吗?
我想要完成的是,如果所有字段都是successNels,那么返回它,否则,返回所有failureNels 的组合.
|@|自上一版Scalaz以来有变化吗?因为即使我做了类似的事情:
().successNel |@| ().successNel
Run Code Online (Sandbox Code Playgroud)
我犯了同样的错误.
更新
我开始探索Scalaz源代码,我发现+++它似乎做了我想要的.
+++和之间有什么区别|@|?
Tra*_*own 10
Scalaz的applicative builder语法(|@|)为您提供了一种将"提升"函数转换为applicative functor的方法.假设我们有以下结果,例如:
val xs: ValidationNel[String, List[Int]] = "Error!".failNel
val ys: ValidationNel[String, List[Int]] = List(1, 2, 3).success
val zs: ValidationNel[String, List[Int]] = List(4, 5).success
Run Code Online (Sandbox Code Playgroud)
我们可以将列表连接函数(++)解除为Validation这样:
scala> println((ys |@| zs)(_ ++ _))
Success(List(1, 2, 3, 4, 5))
scala> println((xs |@| ys)(_ ++ _))
Failure(NonEmptyList(Error!))
scala> println((xs |@| xs)(_ ++ _))
Failure(NonEmptyList(Error!, Error!))
Run Code Online (Sandbox Code Playgroud)
这种语法有点奇怪 - 例如,它与你在Haskell中将函数提升为应用程序函数的方式非常不同,并且这种方式设计主要是为了超越Scala相当愚蠢的类型推理系统.有关更多讨论,请在此处查看我的答案或在此处发布博
古怪的一部分 xs |@| ys并不是真正意义上的任何东西 - 它本质上是一个参数列表,它等待应用于一个函数,它将升级到它的应用函子并适用于它自己.
在+++上Validation一个更简单的一种生物,它只是加法运算的Semigroup实例的类型(注意,您可以同样使用Scalaz的半群运营商|+|在这里的地方+++).你Validation用匹配的半群类型给它两个结果,它给你另一个Validation- 不是一些可怕的ApplyOps东西.
作为旁注,在这种情况下,Validation半群的加法运算与右侧的半群运算相同Validation:
scala> (xs |+| ys) == (xs |@| ys)(_ |+| _)
res3: Boolean = true
Run Code Online (Sandbox Code Playgroud)
然而,情况并非总是如此(\/例如,这不是因为半群积累了错误但是应用仿函数没有).