Validation Scalaz:如何累积失败或将函数应用于不同类型的验证?

Validation Scalaz:如何累积失败或将函数应用于不同类型的验证?,validation,scala,scalaz,Validation,Scala,Scalaz,我有19个字符串需要验证为各种类型。当all验证成功后,我想实例化一个表示电子表格行的类(其中列的类型不同) 当一个或多个字符串无法验证时,我希望在非空列表中累积错误 如果有12个或更少的项目,我可以使用|@或apply12。如果我使用for表达式,它会很快失败,并且不会发生累积 当for表达式失败时,我可以对失败进行排序,但这意味着我将循环两次。是否有一种方法可以使用scalaz将每次验证成功拉入一个变量中(如果我使用for表达式实例化该类,就会发生这种情况),同时累积所有失败?假设我们有一个

我有19个字符串需要验证为各种类型。当all验证成功后,我想实例化一个表示电子表格行的类(其中列的类型不同)

当一个或多个字符串无法验证时,我希望在非空列表中累积错误

如果有12个或更少的项目,我可以使用|@或apply12。如果我使用for表达式,它会很快失败,并且不会发生累积


当for表达式失败时,我可以对失败进行排序,但这意味着我将循环两次。是否有一种方法可以使用scalaz将每次验证成功拉入一个变量中(如果我使用for表达式实例化该类,就会发生这种情况),同时累积所有失败?

假设我们有一个case类(可能有12个以上的成员):

我们将错误表示为字符串,并为方便起见定义了类型别名:

type ErrorOr[A] = ValidationNel[String, A]
我们还有一些验证结果:

val goodA: ErrorOr[Int] = 1.success
val goodB: ErrorOr[Char] = 'a'.success
val goodC: ErrorOr[Symbol] = 'a.success
val goodD: ErrorOr[String] = "a".success

val badA:  ErrorOr[Int] = "x".failNel
val badC:  ErrorOr[Symbol] = "y".failNel
现在我们可以写:

val foo = (Foo.apply _).curried

val good: ErrorOr[Foo] = goodD <*> (goodC <*> (goodB <*> (goodA map foo)))
val bad:  ErrorOr[Foo] = goodD <*> (badC  <*> (goodB <*> (badA  map foo)))
在Haskell中,这将是-你只需写:

Foo <$> goodA <*> goodB <*> goodC <*> goodD
Foo goodA goodB goodC goodD

不幸的是,Scala较弱的类型推断要求我们以错误的顺序编写参数。

这有点笨拙,但您可以,这将累积错误,并且不会对其应用的次数有任意限制。您能否将字符串列表映射到
验证
,然后通过
isFailure
对结果列表进行
分区
。这对我来说很有效,但如果没有一组紧密的参数,那就太好了。:)请注意,我已经使用编写了一些备选方案。
scala> println(good)
Success(Foo(1,a,'a,a))

scala> println(bad)
Failure(NonEmptyList(x, y))
Foo <$> goodA <*> goodB <*> goodC <*> goodD