Cats Effect : Pure Functional way to code in Scala

Reading Time: 2 minutes

Follow 5 Simple Rules with Cats

Program written using Cats Effect provides incredibly strong guarantees and powerful functionality, performance, safety, and composability, provided you follow each of the following rules:

  1. Wrap all side-effects in delayasyncblocking, or interruptible
    • (pro tip: try to keep the size of your delay blocks small; two delays with a flatMap is much better than one big delay)
  2. Use bracket or Resource for anything which must be closed
  3. Never hard-block a thread outside of blocking or interruptible
  4. Use IOApp instead of writing your own def main
  5. Never call anything that has the word unsafe in the name
import cats.effect._
object Main extends IOApp.Simple {
  val run = IO.println("Hello, World!")
}

Or, if you need the ability to take arguments and return exit codes:

import cats.effect._
object Main extends IOApp {
  def run(args: List[String]): IO[ExitCode] =
    if (args.headOption.map(_ == "--do-it").getOrElse(false))
      IO.println("I did it!").as(ExitCode.Success)
    else
      IO.println("Didn't do it").as(ExitCode(-1))
}

If you follow these rules, and you use libraries and frameworks which also follow these rules, you will get a truly astonishing array of things essentially for free:

  • Extremely high performance, elastic, and scalable applications
  • Proven backpressure mechanisms under extreme load in real deployments
  • Reliable resource safety in all cases
  • Aggressive interruption of unnecessary work (e.g. timeouts), automatically, without any extra implementation effort
  • Cats Effect provides Composable and modular application architecture (real, practical functional programming)
  • Simple, safe, and incredibly powerful concurrency mechanisms that get faster under high contention
  • The Highly tuned application runtime with optimized threading and memory management semantics
  • Powerful and orthogonal abstractions which enable architectural decomposition that scales to any problem space
  • Access to an entire ecosystem of uniquely powerful libraries and tooling

Cats Effect System

The typical Cats Effect system is often built in terms of simple, orthogonal, primitive capabilities which come together to represent all the expressive power necessary to encode a modern asynchronous runtime. Much like how the rules of addition, multiplication, and integers come together to define much of what we understand about basic arithmetic, so too do the rules of FunctorMonad, and Concurrent come together to define the nature of a program which has all the capabilities you need.

Cats Effect isn’t just designed to enable high performance applications with out-of-the-box safety and elasticity under load. It was intended first and foremost as a tool for implementing composable and reasonable software that is easy to write, easy to test, and easy to evolve as your team and requirements change over time. To achieve this goal, Cats Effect embraces and enables strong, typeful, purely-functional programming styles that are uniquely tailored for the Scala language.

Getting started

Add the following to your build.sbt:

libraryDependencies += "org.typelevel" %% "cats-effect" % "3.2.2"
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")

To create a new Cats Effect application, place the following contents into a new Scala file within your project:

import cats.effect.{IO, IOApp}

object HelloWorld extends IOApp.Simple {
  val run = IO.println("Hello, World!")
}

Once you have saved this file, you should be able to run your application using sbt run, and as expected, it will print Hello, World! to standard out. 

Testing

The easiest way to write unit tests which use Cats Effect is with MUnit and MUnit Cats Effect. To get started, add the following to your build.sbt:

libraryDependencies += "org.typelevel" %% "munit-cats-effect-3" % "1.0.3" % Test

Acknowledgements

My interest in Cats Effects, as well as some of API in cats-effects was influenced by:

  • Cats-effect by typelevel
  • Cats Effect The pure asynchronous runtime for Scala  by @Typelevel

Leave a Reply