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

旧时模样 提交于 2019-11-30 13:54:44
Travis Brown

Suppose we have a case class (which could have more than twelve members):

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:

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

Scala's weaker type inference requires us to write the arguments in the wrong order, unfortunately.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!