Using scalaz, you have Validation[E, A] , which is similar to Either[E, A] , but has the property that if E is a semigroup (which means elements that can be combined, such as lists), than a few confirmed The results can be combined in a way that contains all the errors that have occurred.
Using Scala 2.10-M6 and Scalaz 7.0.0-M2, for example, where Scalaz has a custom Either[L, R] named \/[L, R] , which defaults to the right side:
import scalaz._, Scalaz._ implicit class EitherPimp[E, A](val e: E \/ A) extends AnyVal { def vnel: ValidationNEL[E, A] = e.validation.toValidationNEL } def parseInt(userInput: String): Throwable \/ Int = ??? def fetchTemperature: Throwable \/ Int = ??? def fetchTweets(count: Int): Throwable \/ List[String] = ??? val res = (fetchTemperature.vnel |@| fetchTweets(5).vnel) { case (temp, tweets) => s"In $temp degrees people tweet ${tweets.size}" }
Here, result is a Validation[NonEmptyList[Throwable], String] , either containing all errors (temperature sensor error and / or twitter error , either )) or a successful message. You can return to \/ for convenience.
Note. The difference between Either and Validation lies mainly in the fact that during verification you can accumulate errors, but you ca flatMap lose flatMap errors, while using it you cannot (easily) accumulate flatMap , but you can flatMap (or in understanding) and, possibly , lose everything except the first error message.
About error hierarchies
I think this may interest you. Regardless of using scalaz / Either / \/ / Validation , I experienced that getting started was easy, but more work is needed in the future. The problem is, how do you collect errors from several erroneous functions in a meaningful way? Of course, you can just use Throwable or List[String] everywhere and have an easy time, but not too useful or interpretable. Imagine you get a list of errors, such as "child age missing" :: "I / O error reading file" :: "division by zero".
Thus, my choice is to create error hierarchies (using ADTs), just as you could wrap checked Java exceptions in a hierarchy. For example:
object errors { object gamestart { sealed trait Error case class ResourceError(e: errors.resource.Error) extends Error case class WordSourceError(e: errors.wordsource.Error) extends Error } object resource { case class Error(e: GdxRuntimeException) } object wordsource { case class Error(e: Any) } }
Then, using the result of erroneous functions with different types of errors, I join them under the corresponding parent error type.
for { wordSource <- errors.gamestart.WordSourceError <-: errors.wordsource.Error <-: wordSourceCreator.doCreateWordSource(mtRandom).catchLeft.unsafePerformIO.toEither resources <- errors.gamestart.ResourceError <-: GameViewResources(layout) } yield ...
Here f <-: e maps the function f left of e: \/ , since \/ is a bifunctor. For se: scala.Either you can have se.left.map(f) .
This can be further improved by providing a shapeless HListIso to be able to draw beautiful error trees.
Revisions
Updated: (e: \/).vnel raises the failure side in NonEmptyList , so if we have a failure, we have at least one error (was: or not).