Disclaimer Monad transformers have some overhead, so make sure you benchmark before and after switching to them

In a previous post I was exploring the use of the EitherT to make it easier to work with Either when it is nested in a Future. I’m currently reading the book Advanced Scala with Cats and decided to rewrite some of my code using the Cats library instead.

There’s also a page on Herding Cats where Eugene Yokota covers the same ground. I wanted to expand my examples from last post so that they actually execute in a Future so I can map that to my own error handling code in real programs. For example in the Herding Cats blog the demonstration code returns values like this:

  EitherT.right(Future { List(User(1, "Michael")) })

What I wanted to figure out was how this looks in real code where you may have a function that works with a Future[Either]. I went back to my code from last post and modified the dummy functions so that:

  • The code executes in a Future
  • The function returns Cats EitherT type response

This makes things easier at the call site because instead of converting the response from Future[Either[String, A]] as I did then, you can simply use the EitherT directly. So instead of:

 val r: FutureEither[String, Int] = for (
        rb1 <- FutureEither(dummyFunction1(8));
        rb2 <- FutureEither(dummyFunction1(12))
      ) yield rb1 + rb2

you can use the results directly

  {for (
      rb1 <- dummyFunction1(8);
      rb2 <- dummyFunction1(12)

    ) yield (rb1 + rb2)}

If you check the example below the only thing needed to make your function return an EitherT[Future] is to use the EitherT constructor on the final value

   EitherT[Future, String, Int](f)

The other thing you need to know about EitherT in Cats is that you need to use ‘value’ instead of ‘run’ to get into the results at the end.

I found this post useful for more ways to create a Future[Either] stack.

Final thoughts; whilst the the syntax is slightly different when working with EitherT and Cats, Scalaz and the Hamsters library, the concept is the same and it comes down to finding a way to use them that makes them easier to work with at the calling site. I think I can make things even cleaner with an implicit conversion from Future[Either] to EitherT[Future, String, A] but that will be possibly a later post.

Libraries used

Again for reference the libraries used when writing this post are as follow:

   "org.typelevel" %% "cats" % "0.9.0"