# immutables

The code should be easy to read. One of the programming principles to make the code more readable is to avoid nested operations. The so-called pyramid of doom does not only refers to callback hell in javascript but ofter appear in scala as well. Here, I describe how to make the for-comprehensions more elegant when using combined monads in scala.

## Theory

For-comprehensions in scala allows writing easy to read and maintain code. In practice, it is just a syntactic sugar for composing map, flatMap and filter operations. Any class providing them can be used in for-comprehension statement.

For such list of users to get an email by name the following code

can be rewritten using for-comprehension like this

The return type is always the same as the first expression’s type.

In scala we often use context containers (monads) like

• Future[A] - for asynchronous computations,
• Option[A] - for optional values,
• Try[A] - for exception handling,
• Either[A, B] - usually to express an error or a value.

It is possible to use all of them in for-comprehensions.

However, each statement must result in the same type as the first one. It is not possible to mix Either with Option, you need to convert Option to Either in order to use it next to Either resulting statement. Things get even more complicated when you combine monads with each other.

You may have functions that return an async optional value Future[Option[A]] or an async error or value Future[Either[Error, A]]. For this, you need to use nested for-comprehensions.

In this case, for comprehensions are not easy to read as when using single monads..

To avoid nested for-comprehensions you can use a common context container (monad) and transform all expressions into it. In the example above, the combined monad is Future[Either[Error, A]]. If you have a way to transform to result of authenticate and getUser methods into this monad, you can make this for-comprehension look simple.

## Example

I prepared an example that shows how to use scalaz monad transformers to build neat for-comprehensions for a http4s service with combined monads. The example app provides a REST endpoint that authenticates a user using token and gets the user and his devices. The model looks like this:

There are two methods: authenticate a user using token and get a device by id.

Task is a scalaz.concurrent.Future[Throwable \/ A] and is used in http4s a lot. Read more about task here. A \/ B is a scalaz way to express Either[A, B]

UserService’s authenticate function returns asynchronous computation of either error or user. DeviceService’s getByid function return asynchronous computation of optional device.

In order to use both functions in for-comprehension without nesting, we need to use a combined monad.

EitherT[Task, Failure, A] represents something like Future[Either[Failure, A]]. It is a monad transformer. It allows wrapping Either into another monad like Task easily. Result[A] shares the behaviour of Task and Either. In simple terms, it provides flatMap and map methods that do the nesting for you.

It is easy to create a Result[A] of a single value. You just need to do "email".point[Result]. However, to build it from a Task[Option[A]] in a convenient way you need helper functions.

Here, are some functions that simplify creation of a Result[A] and provide a way to express a failure.

|> is the Thrush combinator. In this context it applies the value on the left to a function on the right.

Although, the for-comprehension operates on combined monads the code is not nested. In addition, it handles the cases when Either == Left or Option == None. Complete example can be found at github. Run sbt test to see the spec.

## Summary

There are many resources that cover the monad transformers topic in more detail. Here, I wanted to show a particular problem that can be solved using them and the benefits. I used scalaz and http4s just as an example. Similar functionality can be achieved in vanilla scala as well, but requires more code.