Processing a list of Scalaz6 Validation

喜夏-厌秋 提交于 2020-01-02 02:00:11

问题


Is there an idiomatic way to handle a collection of Validation in Scalaz6?

val results:Seq[Validation[A,B]]
val exceptions = results.collect{case Failure(exception)=>exception}
exceptions.foreach{logger.error("Error when starting up ccxy gottware",_)}
val success = results.collect{case Success(data)=>data}
success.foreach {data => data.push}
if (exceptions.isEmpty)
   containers.foreach( _.start())

I could think of using a fold when looping on results, but what about the final test?


回答1:


The usual way to work with a list of validations is to use sequence to turn the list into a Validation[A, List[B]], which will be be empty (i.e., a Failure) if there were any errors along the way.

Sequencing a Validation accumulates errors (as opposed to Either, which fails immediately) in the semigroup of the left-hand type. This is why you often see ValidationNEL (where the NEL stands for NonEmptyList) used instead of simply Validation. So for example if you have this result type:

import scalaz._, Scalaz._

type ExceptionsOr[A] = ValidationNEL[Exception, A]

And some results:

val results: Seq[ExceptionsOr[Int]] = Seq(
  "13".parseInt.liftFailNel, "42".parseInt.liftFailNel
)

Sequencing will give you the following:

scala> results.sequence
res0: ExceptionsOr[Seq[Int]] = Success(List(13, 42))

If we had some errors like this, on the other hand:

val results: Seq[ExceptionsOr[Int]] = Seq(
  "13".parseInt.liftFailNel, "a".parseInt.liftFailNel, "b".parseInt.liftFailNel
)

We'd end up with a Failure (note that I've reformatted the output to make it legible here):

scala> results.sequence
res1: ExceptionsOr[Seq[Int]] = Failure(
  NonEmptyList(
    java.lang.NumberFormatException: For input string: "a",
    java.lang.NumberFormatException: For input string: "b"
  )
)

So in your case you'd write something like this:

val results: Seq[ValidationNEL[A, B]]

results.sequence match {
  case Success(xs) => xs.foreach(_.push); containers.foreach(_.start())
  case Failure(exceptions) => exceptions.foreach(
    logger.error("Error when starting up ccxy gottware", _)
  )
}

See my answers here and here for more detail about sequence and about Validation more generally.



来源:https://stackoverflow.com/questions/14233511/processing-a-list-of-scalaz6-validation

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