簡體   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