Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Created January 4, 2020 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save djspiewak/ac72649347dc2ce3c384f996d3ea7a58 to your computer and use it in GitHub Desktop.
Save djspiewak/ac72649347dc2ce3c384f996d3ea7a58 to your computer and use it in GitHub Desktop.
scala> run(F.raiseError[String](42).map(_.asRight[Int]).handleErrorWith(_.asLeft[String].pure[PureConc[Int, ?]]))
res11: ce3.ExitCase[Option,Int,Either[Int,String]] = Completed(Some(Left(42)))
scala> run(F.attempt(F.raiseError[String](42)))
res12: ce3.ExitCase[Option,Int,Either[Int,String]] = Errored(42)
@iRevive
Copy link

iRevive commented Jan 6, 2020

Hey, I ran into a similar issue today.

Effect definition:

import cats.data.EitherT
import cats.effect.IO
import cats.syntax.applicativeError._

type F[A] = EitherT[IO, String, A]

val error = new RuntimeException("my error")
val io = IO.raiseError[Either[String, Int]](error)
val fa: F[A] = EitherT(io)

Example #1:

println(fa.attempt.value.unsafeRunSync())

// Throws exception: java.lang.RuntimeException: my error

The compiler chooses EitherT.catsDataMonadErrorForEitherT as MonadError instance and evaluation fails.

Example #2:

println(ApplicativeError[F, Throwable].attempt(fa).value.unsafeRunSync())

// Output: Right(Left(java.lang.RuntimeException: my error))

In this case, the compiler chooses EitherT.catsDataMonadErrorFForEitherT and everything works fine.

The catsDataMonadErrorForEitherT has higher priority then catsDataMonadErrorFForEitherT until the error type is not provided explicitly.

@djspiewak
Copy link
Author

Wow! That is absolutely fascinating and concerning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment