Functional error handling. Execute all handlers

Viewed 211

I have multiple values F[A] which may finish their evaluation with some error. There are some actions to be done in case an error occurred. How to execute handlers for all of the values, not just the first at which an error occurred?

For example

import cats.implicits._
import cats.effect._

class Test[F[_]: Sync] {

  def executeAllHandlers[A, B, C](fa: F[A], fb: F[B], fc: F[C]): F[(A, B, C)] =
    for {
      a <- fa
      b <- fb
      c <- fc
    } yield (a, b, c)
}

object Test extends App{
  val ioa: IO[Int] = IO.raiseError(new Error) onError {
    case _ => IO(println("ioa"))
  }

  val iob: IO[String] = IO.raiseError(new Error) onError {
    case _ => IO(println("iob"))
  }

  val ioc: IO[Double] = 2.5.pure[IO]

  //prints ioa and fails with Error
  new Test[IO].executeAllHandlers(ioa, iob, ioc).unsafeRunSync() 
}

The thing that I want to achieve is to execute handlers for all faulty evaluations which in the case above are ioa and iob and fails with an error (does not matter which one).

Is it possible to achieve something like this in cats? Maybe mtl typeclasses can be helpful here?

1 Answers

Applying a hint given by @LuisMiguelMejíaSuárez here is how the function can be modified so all handlers are executed

def executeAllHandlers[A, B, C](fa: F[A], fb: F[B], fc: F[C]): F[(A, B, C)]=
(for {
  a <- fa.attempt
  b <- fb.attempt
  c <- fc.attempt
} yield for {
  a <- a
  b <- b
  c <- c
} yield (a, b, c)).flatMap(Sync[F].fromEither)

Now it executed both of the handler and then throws Error.

ioa
iob
Exception in thread "main" java.lang.Error
Related