展平嵌套Scalaz验证

时间:2012-06-23 22:54:56

标签: scala scalaz

我对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]

这适用于并返回正确的类型和结果。然而,它感觉不是正确的解决方案,所以我必须遗漏一些东西。我最近需要做些什么来避免这种可怕的折叠?

1 个答案:

答案 0 :(得分:10)

您在这里寻找的是monadic join

问题是Validation本身并不是真正的monad,因为错误方带有Semigroup无法由Monad保留的Either结构。但如果需要,你可以随时下载到flatMap monad。此功能由(validateXyz(...) |@| validateAbc(...))(otherFunction).flatMap(x => x) 提供。

Applicative

如果外部有错误,结果将是该错误。如果您在成功中有错误,结果将是内部错误。否则结果将是成功的。请注意,内部和外部都不可能出现错误。这就是为什么如果要组合错误,必须使用Monad而不是{{1}}。