简体   繁体   中英

Cats MonadError with Try doesn't complie

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?

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM