the reader monad

  • function composition in scala
  • dependency injection with the reader monad
  • using the reader alongside the cake pattern
  • possible problems and solutions

composing functions

the only language construct we need

scala> val f = (i: Int) => i*3
f: Int => Int = <function1>

f: Int => Int is just a fancy way of saying Function1[Int, Int]

 def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
scala> val f = (i: Int) => i*3
f: Int => Int = <function1>

scala> val g = (i: Int) => i.toString
g: Int => String = <function1>scala> val tripleToString = f andThen gtripleToString: Int => String = <function1>
scala> tripleToString(2) res0: String = 6


 A type with a monad structure defines what it means to chain operations, or nest functions of that type together.


  • a monad for unary operations
  • using andThen as a map operation
  • in the end its just a Function1
  • scalaz.Reader provides map and flatMap operations


scala> import scalaz.Reader
import scalaz.Reader

scala> val f = Reader((i: Int) => i*3)
f: scalaz.Reader[Int,Int] = scalaz.KleisliFunctions$$anon$17@53628ee
new readers can be created with map and flatMap
val g = f map (i => i + 2)
val h = for (i <- g) yield i.toString

dependency injection with the reader monad

define functions requiring a dependency as a Reader with the dependency

let's see an example

trait Users {
  def getUser(id: Int) = Reader((userRepository: UserRepository) =>

  def findUser(username: String) = Reader((userRepository: UserRepository) =>
getUser returns a Reader[UserRepository, User] not a User!

what does that mean?

I'm gonna return a User, when I get a UserRepository

The actual injection is deferred

map, flatmap all the monadic goodness

object UserInfo extends Users {
def userEmail(id: Int) = { getUser(id) map ( } def userInfo(username: String) = for { user <- findUser(username) boss <- getUser(user.supervisorId) } yield Map( "fullName" -> s"${user.firstName} ${user.lastName}", "email" -> s"${}", "boss" -> s"${boss.firstName} ${boss.lastName}" )}
userEmail returns Reader[UserRepository, String]

but we don't have to mention the Repository anywhere except our primitive Readers

multiple dependencies?

trait Repositories {
  def userRepository: UserRepository
  def questionRepository: QuestionRepository
Now we just have to change our primitive readers to accept the Repositories instead of a single one

trait Users {
  def getUser(id: Int) = Reader((repos: Repositories) =>
getUser is now a Reader[Repositories, User]

Injecting the dependency

At an outer level of our application we actually need to inject the dependencies

object Application extends Application(UserRepositoryImpl)

class Application(userRepository: UserRepository) with Users {

  def getUserEmail(id: Int) = Action {


why not use it with cake together?

object Application extends Application with UserRepositoryComponentImpl

trait Application extends Controller with Users {
  this: UserRepositoryComponent =>

  def getUserEmail(id: Int) = Action {
  • Cake pattern at the outer edge
  • Reader monad in the core 
  • Reader monad lets us push the dependency injection from the core to the outer levels too


what about futures?

  • Two monads do not combine automatically
  • Future[Reader[A,B]], Future[Reader[A, Future[B]]] ?!
  • Better to have reader of futures that we can combine
  • Monad transformers in scalaz or simple implicit conversions

additional readings and inspiration

Tooling the reader monad (working with Futures)

The Reader monad for dependency injection

By danielbedo

The Reader monad for dependency injection

Using the Reader monad for dependency injection

  • 7,692
Loading comments...