[英]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])(_ |@| _)
}
minValidate
和sizeValidate
函數只返回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.