In Scalaz
Kleisli[F, A, B]
is a wrapper forA => F[B]
.ReaderT[F, A, B]
-- reader monad transformer -- is just an alias ofKleisli[F, A, B]
.Reader[A, B]
monad is a specialization ofReaderT
with identity monadId
:
type Reader[A, B] = ReaderT[Id, A, B]
.
Is it just a coincidence or there are some deeper reasons that Kleisli
, ReaderT
, and Reader
are isomorphic in Scalaz ?
You can think of it as arriving at the same place by two different routes. On one side you start with the reader monad, which is simply a kind of wrapper for functions. Then you realize that you want to integrate this reader functionality into a larger monad with other "effects", so you create a
ReaderT
monad transformer. At that point it makes sense to implement your originalReader[E, ?]
asReaderT[Id, E, ?]
.From the other side, you want a type to represent Kleisli arrows (i.e. functions with a monadic return type). It turns out that this is the same thing as
ReaderT
, so you just make that an alias.There's nothing terribly mysterious about the "it turns out" part. It's a little like if you started out with an
Addable
type class for number-like things, then decide to make it more generic, and eventually end up with a type class that just provides an associative "addition-like" operation. You've reinventedSemigroup
! You may still want to keep theAddable
name around, though, for historical or pedagogical reasons, or just for convenience.That's all that's happening with
Reader
andReaderT
—you don't need these aliases, but they can be convenient, and may help improve the clarity of your code.