Alejandro Echeverri Alejandro Echeverri - 1 month ago 8
Scala Question

Why does cats returns `Id[T]` in the evaluation of a Reader?

I've used

Kleisli
before and, when you evaluate the computation passing the dependency to it the monad returns the value that I need.
Now I'm using
Reader
and I see that when I run the program the evaluation is returned wrapped in an
Id
.

Why?

Also, exploring the different options that
Id
has I encountered with
init
function that unwraps the computed value. Is it good to use that "combinator"? The only thing that I need from the
Reader
is the produced value without any wrapper.

Thanks

Answer Source

Id is defined as type Id[A] = A. So it's just the type itself, and you can use it as if there was no Id there.

The following code is valid:

val s: Id[String] = "123"
s.charAt(s.length - 1) 

As cats documentation states:

Identity, encoded as type Id[A] = A, a convenient alias to make identity instances well-kinded.

The identity monad can be seen as the ambient monad that encodes the effect of having no effect. It is ambient in the sense that plain pure values are values of Id.

For instance, the cats.Functor instance for cats.Id allows us to apply a function A => B to an Id[A] and get an Id[B]. However, an Id[A] is the same as A, so all we're doing is applying a pure function of type A => B to a pure value of type A to get a pure value of type B. That is, the instance encodes pure unary function application.

For instance, for Reader it's more convenient to define it as:

type Reader[A, B] = ReaderT[Id, A, B]
type ReaderT[F[_], A, B] = Kleisli[F, A, B]

This allows you to define all the typeclass instances for the more complex case when F[_] is something real, and just use those instances for the simpler case when there is no F[_] (i.e., when F is Id).