<img height="1" width="1" src="https://www.facebook.com/tr?id=1076094119157733&amp;ev=PageView &amp;noscript=1">

Don’t listen to them, learn Cats this way

Posted by Amir Karimi on Mon, Jan 29, 2018

OK, you came to the conclusion that type-safety is good; it helps you get things done in a safer manner, at least for whatever you’re working on at the moment. So you started using types more than before to describe what a piece of code does without the need to run; in other words, to bring forward unwanted errors.

One of the first things you may have found quite handy when starting to use Scala is Option type, after which it simply no longer makes sense to deal with nulls.

Have a look at this piece of code for instance:

It obviously feels safer than a null checking if block. The author of getUser method lets the consumer know what they should expect to happen when they call it. The result would be either a User object or nothing. On the other hand, thanks to the pattern matching, the consumer would be able to handle the possible results in an elegant way. Even better, the compiler would warn you (which can be converted to an error) if you forget to check all possible cases.

From a pragmatic point of view, one would argue that Scala is all about scalability, and asynchronous programming is one of the fundamentals of scalability.

Instead of having some fancy keywords, magic and hiding things (like C# 5 and others), Scala has chosen a direct answer: Future type; as a result, it’s more likely that you’ll see methods returning Future of something in real-world idiomatic Scala codebases:

Again, method signature explains everything. The only difference is that it’s async and the consumer uses map to match the result. So far so good.

We always see this kind of cool, small code samples in fancy programming languages, but real-world software is not that simple and isolated. You always need to combine things together and that is where those lovely code samples don’t look shiny anymore.

Consider the following example where we want to find the user country by its ID asynchronously:

Despite the expressiveness of the method signatures, the code is not as beautiful as before. Although there is a pattern here, it doesn’t look as smooth and as readable.

This is one of the most common situations for a developer who is new to functional programming where a library like Cats comes in handy.

Meet OptionT. It's basically a container type wrapping two other types; another container type like Future and a generic type like User (OptionT[Future, User]). This provides more abstraction. Let’s rewrite the above sample with OptionT:

Far more beautiful, concise and readable.

Now if we go a little bit further, we can do the same with Either. There has always been an argument about using Either vs exceptions when dealing with Future. I don’t believe that all exceptions should be modelled as Either, but even for those which makes sense, many developers would argue that Either increases the complexity as you need to extract inner types to have access to the inner values. This is true when you’re dealing with real-world applications, but the good news is that Cats support the same concept for Either via EitherTSo the following code:

Can be rewritten using EitherT like this:

I’d say Future[Either[String, Option[User]] would be a more realistic type to deal with, but it needs its own separate blog post which will also show that Cats or Scalaz are not always the answer to everything and sometimes there are simpler ways to make the code clean and readable.

Conclusion

You don’t need to know about monads and category theory to start using Cats. Types like OptionT and EitherT are called monad transformers but you don’t need to know their names before you start using them.

This doesn’t mean that you should ignore those theory concepts. The rule of thumb for learning abstract concepts is to use metaphors, and you tell me, what metaphor can be better than the real-world use cases of that abstract concept? Note that it's not just about Cats or Scalaz; most of the time, we start with the solutions rather than starting with a firm understanding of the actual problem.

Recent Posts

Posts by Topic

see all

Subscribe to Email Updates