Validation 应用函子|@|不工作的Scalaz验证

Validation 应用函子|@|不工作的Scalaz验证,validation,scala,scalaz,scalaz7,Validation,Scala,Scalaz,Scalaz7,我正在尝试在我的应用程序中使用Scalaz 7验证。但是,我在使用|@|应用程序functor合并失败时遇到了一个问题。以下是我的代码: type ValidationResult = ValidationNel[String, Unit] def validate[A: ClassTag](instance: A, fieldNames: Option[Seq[String]] = None): ValidationResult = { val fields = classTag[A

我正在尝试在我的应用程序中使用Scalaz 7验证。但是,我在使用
|@|
应用程序functor合并失败时遇到了一个问题。以下是我的代码:

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])(_ |@| _)
}
minValidate
sizeValidate
函数只返回
ValidationResults

问题是,这段代码无法编译。错误消息是:

Type mismatch, expected F0.type#M[NotInferedB], actual: ValidationResult
我不知道那是什么意思。。。我需要给Scala更多的类型信息吗

我试图实现的是,如果所有字段都是
successNel
s,则返回该字段,否则返回所有
failureNel
s字段的组合

自上一版本的Scalaz以来,
|@|
是否已更改?因为即使我做了这样的事情:

().successNel |@| ().successNel
我也犯了同样的错误

更新

我开始搜索Scalaz源代码,找到了
++
,它似乎满足了我的需求


++
|@|
之间有什么区别?

Scalaz的应用程序生成器语法(
|@|
)提供了一种将函数“提升”到应用程序函子的方法。假设我们有以下结果,例如:

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
我们可以将列表串联函数(
++
)提升到
验证中,如下所示:

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!))
这种语法有点奇怪,它与在Haskell中将函数提升为应用程序函子的方式非常不同,它的设计主要是为了比Scala相当愚蠢的类型推断系统更聪明。有关更多讨论,请参阅或

奇怪的是,
xs|@|ys
本身并不意味着什么,它本质上是一个参数列表,等待应用于一个函数,然后将其提升到其应用函子并应用于自身

验证
上的
++
是一种简单得多的生物,它只是类型的
半群
实例的加法操作(请注意,您可以在这里等效地使用Scalaz的半群操作符
++
来代替
++
)。你给它两个匹配半群类型的
验证
结果,它给你另一个
验证
——不是什么可怕的
ApplyOps
东西


作为旁注,在这种情况下,
验证
的半群的加法操作与右侧提升到
验证
的半群操作相同:

scala> (xs |+| ys) == (xs |@| ys)(_ |+| _)
res3: Boolean = true
然而,情况并非总是如此(例如,对于半群累积错误而应用函子不累积错误的情况,
\/