我对scalaz很新,我从验证开始。
我有一些表格的验证功能:
def validateXyz(...): ValidationNEL[String, String] = ...
然后我使用applicative样式组合多个验证,然后调用另一个也返回验证的函数:
(validateXyz(...) |@| validateAbc(...)) { (first, second) =>
otherFunction(first, second)
}
其中,
def otherFunction(first: String, second: String): ValidationNEL[String, String] = ...
但是,在调用上面的结果时,结果是:
val result: ValidationNEL[String, ValidationNEL[String, String]] = ...
我可以通过使用两个函数调用结果上的fold来解压缩这个函数,第一个将NEL传播为失败,第二个只传播其参数:
def propagateF(result: NonEmptyList[String]): ValidationNEL[String, String] = result.fail
def propagateV(result: ValidationNEL[String, String]) = result
result.fold(propagateF, propagateV)
// result type: ValidationNEL[String, String]
这适用于并返回正确的类型和结果。然而,它感觉不是正确的解决方案,所以我必须遗漏一些东西。我最近需要做些什么来避免这种可怕的折叠?
答案 0 :(得分:10)
您在这里寻找的是monadic join
。
问题是Validation
本身并不是真正的monad,因为错误方带有Semigroup
无法由Monad
保留的Either
结构。但如果需要,你可以随时下载到flatMap
monad。此功能由(validateXyz(...) |@| validateAbc(...))(otherFunction).flatMap(x => x)
提供。
Applicative
如果外部有错误,结果将是该错误。如果您在成功中有错误,结果将是内部错误。否则结果将是成功的。请注意,内部和外部都不可能出现错误。这就是为什么如果要组合错误,必须使用Monad
而不是{{1}}。