Here are my notes from the book Essential Effects .
I really love this book as it explained a lot of concepts that are used in functional programming and the cats effect ecosystem.
I love how the examples were concise and practical.
I Would have loved if there was more on Testing effects, but there was an introductory chapter.
I totally recommend this book for anyone who wants to dive deeper into functional programming principles and understand more of the cats effect library
Higher Kinded type
A higher-kinded type which is also called a type constructor describes types that require a type to be a concrete type.
An example is the Option data type:
Continue reading “Essential Effects 01: Terminologies”
Constructing an IO
An IO can be constructed using IO.delay to capture side effects as an IO value
val stringIO : IO[String] = IO.delay("Hello World!")
Most often, people will use the apply method which internally just calls the delay method.
Continue reading “Essential Effects 02: Cats Effect IO”
Futures which are higher kinded F[_] types support parallelism by scheduling work on multiple threads via a scala.concurrent.ExecutionContext. This thus means that we can make Futures run in sequence and in parallel.
Continue reading “Essential Effects 03: Functional Parallelism”
Let’s see this example:
Forking, Joining and cancelling an effect
As explained by the use of
ParallelIOwhich is more or less the effectful form of Futures.
It thus means that there has to be a way to run effects concurrently and/or in parallel.
It means there must be a wy to run our effect on another thread, wait for it to finish, and
To explain this, we will try to rewrite the
Continue reading “Essential Effects 04: Granular Parallelism (Fibers)”
parMapN function that comes with cats effect, but we”ll call ours
myParMapN with the following signature:
CPU vs IO Bound work
IO Bound work
IO operations typically involves reading or writing to files, databases, sockets e.t.c. Most of these times, waiting is involved as sometimes data isn’t yet available.
In these scenarios, the CPU will have to wait until the underlying hardware has delivered the data since it is not immediately available.
Any IO operation that requires reading or writing using anything that is not stored in RAM
Continue reading “Essential Effects 05: Contexts and Thread Pools”
will cause something called IOwait, which is basically a system call that tells the CPU to pause the execution og the current thread until data is available or data has been successfully transmitted. This way. the CPU can easily pause that thread and move on to do other things.
We’ve dealt a lot with IO values, but in practice, we may have to deal with legacy
codebases that use futures or other async structures. But since we are writing pure functional programs, we need a way to be able to capture or lift the result of these asynchronous computations into an IO.
Cats effect provides that capability via the
IO.async method. The way this works is that the method takes a function from a callback to Unit, where the callback itself is a function from an Either[Throwable,A] to Unit.
The function signature looks like this
Continue reading “Essential Effects 06: Integrating with Legacy systems”
In Cats Effect, the Resource data type represents this acquire-use-release pattern to
manage state. In other words, a Resource represents acquisition of an entity with its release function already implemented, which will be called once that resource has been used.
To acquire and use a resource, we call
Continue reading “Essential Effects 07: Managing Resources”
Resource.make which has this type signature:
It’s bad to use vars to define state that’s going to be shared by multiple threads, the same
Continue reading “Essential Effects 08: Concurrent Coordination”
goes for using vars for using vars for sharing state amongst multiple effects.
Before we start talking about monad transformers, let’s talk about why we may need them.
Let’s say we define the following classes and functions in this contrived example:
case class User(name : String) extends AnyVal
case class Order(order : String) extends AnyVal
case class DeliveryDetails(detail : String) extends AnyVal
def getUser(name : String) : Future[Option[User]] = ???
def getOrder(user : User) : Future[Option[Order]] = ???
def getDeliveryDetails(order : Order) : Future[Option[DeliveryDetails]] = ???
If we want to get the delivery details of a particular user, we can easily do this via a for-comprehension:
Continue reading “Monad Transformers”