简体   繁体   English

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

[英]Scalaz: how can I accumulate Failures or apply a function to Validations with different types?

I have 19 strings that need to be validated into various types. 我有19个字符串需要验证为各种类型。 When all validate successfully, I would like to instantiate a class that represents a row of a spreadsheet (where the columns do not all have the same type). 当所有验证成功时,我想实例化一个表示电子表格行的类(其中列不是全部具有相同的类型)。

When one or more of the strings fails to validate, I would like to have the errors accumulated in a NonEmptyList. 当一个或多个字符串无法验证时,我希望在NonEmptyList中累积错误。

If there were 12 or fewer items, I could use |@| 如果有12个或更少的项目,我可以使用| @ | or apply12. 或申请12。 If I use a for expression, it fails fast and no accumulation happens. 如果我使用for表达式,它会快速失败并且不会发生累积。

I could sequence the failures when the for expression fails, but that means I'm looping twice. 当for表达式失败时,我可以对失败进行排序,但这意味着我循环两次。 Is there a way to use scalaz to pull each validation success into a variable (as would happen if i used a for expression to instantiate the class) at the same time as accumulating all of the failures? 有没有办法使用scalaz将每个验证成功拉入变量(如果我使用for表达式来实例化类),同时累积所有失败?

Suppose we have a case class (which could have more than twelve members): 假设我们有一个案例类(可能有超过12个成员):

case class Foo(a: Int, b: Char, c: Symbol, d: String)

And that we're representing errors as strings and have defined a type alias for convenience: 并且我们将错误表示为字符串并为方便起见定义了类型别名:

type ErrorOr[A] = ValidationNel[String, A]

We also have some validation results: 我们还有一些验证结果:

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

Now we can write: 现在我们可以写:

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)))

Which gives us what we want: 这给了我们想要的东西:

scala> println(good)
Success(Foo(1,a,'a,a))

scala> println(bad)
Failure(NonEmptyList(x, y))

In Haskell this would be much prettier —you'd just write: 在Haskell中,这会更漂亮 - 你只需写:

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

Scala's weaker type inference requires us to write the arguments in the wrong order, unfortunately. 不幸的是,Scala的弱类型推断要求我们以错误的顺序编写参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM