繁体   English   中英

使用applicative functor进行Scalaz验证| @ | 不工作

[英]Scalaz Validation with applicative functor |@| not working

我正在尝试在我的应用中使用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])(_ |@| _)
}

minValidatesizeValidate函数只返回ValidationResults

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

Type mismatch, expected F0.type#M[NotInferedB], actual: ValidationResult

我不知道这意味着什么......我需要给Scala更多的类型信息吗?

我想要完成的是,如果所有字段都是successNel ,则返回,否则,返回所有failureNel的组合。

|@| 自上一版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

我们可以将列表连接函数( ++ )提升到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!))

这种语法有点奇怪 - 例如,它与你在Haskell中将函数提升为应用程序函数的方式非常不同,并且这种方式设计主要是为了超越Scala相当愚蠢的类型推理系统。 有关更多讨论,请在此处查看我的答案在此处 发布博

奇怪的一部分是xs |@| ys xs |@| ys本身并不代表任何东西 - 它本质上是一个参数列表,它等待应用于一个函数,它将被提升到它的应用函子并适用于它自己。

+++Validation一个更简单的一种生物,它只是加法运算的Semigroup实例的类型(注意,您可以同样使用Scalaz的半群运营商|+|这里代替+++ )。 你给它两个Validation结果与匹配的半群类型,它给你另一个Validation - ApplyOps一些可怕的ApplyOps事情。


作为旁注,在这种情况下, Validation的半群的加法运算与右侧的半群运算相同,进入Validation

scala> (xs |+| ys) == (xs |@| ys)(_ |+| _)
res3: Boolean = true

但情况并非总是如此(例如,它不是用于\\/ ,半群累积错误但应用函子不存在的情况)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM