Home > Net >  Cats MonadError with Try doesn't complie
Cats MonadError with Try doesn't complie

Time:11-28

I just found a MonadError code snippet that uses Either like the following

  import cats.MonadError
  import cats.instances.either._ // for MonadError

  type ErrorOr[A] = Either[String, A]
  val monadError = MonadError[ErrorOr, String]

  val success = monadError.pure(42)
  println(success)
  // success: ErrorOr[Int] = Right(42)

  val failure = monadError.raiseError("Badness")
  println(failure)
  // failure: ErrorOr[Nothing] = Left("Badness")

The above code compiles and gives expected result. Then I tried to do the same for Try

  import cats.MonadError
  import cats.instances.try_._
  type TryOr[A] = Try[A]
  val monadError = MonadError[TryOr, String]

  val success = monadError.pure(42)
  println(success)

  val failure = monadError.raiseError("Badness")
  println(failure)

this code doesn't compile. it says no implicit found for parameter F:MonadError[TryOr, String] I went to the definition of MonadError and found following.

object MonadError {
  def apply[F[_], E](implicit F: MonadError[F, E]): MonadError[F, E] = F
}

But didn't understand why it worked for Either but not working for Try. Why we need additional implicit even after import cats.instances.try_._

Can you help understand what is happening in the background ?

CodePudding user response:

With Try you should use only Throwable as an error type. This is a limitation of the Try design. MonadError[Throwable, A]. You can check Try instances cats.instances.TryInstances. There is only MonadThrow instance.

  type TryOr[A] = Try[A]
  val monadError = MonadThrow[TryOr]

  val success = monadError.pure(42)
  println(success)

  val failure = monadError.raiseError(new Exception("Badness"))
  println(failure)
  • Related