In the chapter about applicatives, we saw that the function type, `(->) r` is an instance of `Functor`.

``````scala> import cats._, cats.data._, cats.implicits._
import cats._
import cats.data._
import cats.implicits._
scala> val f = (_: Int) * 2
f: Int => Int = \$\$Lambda\$3456/1539035418@7ffd2d46
scala> val g = (_: Int) + 10
g: Int => Int = \$\$Lambda\$3457/958540109@37abac8f
scala> (g map f)(8)
res0: Int = 36``````

We’ve also seen that functions are applicative functors. They allow us to operate on the eventual results of functions as if we already had their results.

``````scala> val h = (f |@| g) map {_ + _}
<console>:22: warning: method |@| in class SemigroupalOps is deprecated (since 1.0.0-MF): Replaced by an apply syntax, e.g. instead of (a |@| b).map(...) use (a, b).mapN(...)
val h = (f |@| g) map {_ + _}
^
h: Int => Int = scala.Function1\$\$Lambda\$2547/1273946735@57aa485b
scala> h(3)
res1: Int = 19``````

Not only is the function type `(->) r a` functor and an applicative functor, but it’s also a monad. Just like other monadic values that we’ve met so far, a function can also be considered a value with a context. The context for functions is that that value is not present yet and that we have to apply that function to something in order to get its result value.

Let’s try implementing the example:

``````scala> val addStuff: Int => Int = for {
a <- (_: Int) * 2
b <- (_: Int) + 10
} yield a + b
addStuff: Int => Int = cats.instances.Function1Instances\$\$anon\$2\$\$Lambda\$3460/1901797297@e05983e
res2: Int = 19``````

Both `(*2)` and `(+10)` get applied to the number `3` in this case. `return (a+b)` does as well, but it ignores it and always presents `a+b` as the result. For this reason, the function monad is also called the reader monad. All the functions read from a common source.

The `Reader` monad lets us pretend the value is already there. I am guessing that this works only for functions that accepts one parameter.

Dependency injection

At nescala 2012 on March 9th, Rúnar (@runarorama) gave a talk Dead-Simple Dependency Injection. One of the ideas presented there was to use the `Reader` monad for dependency injection. Later that year, he also gave a longer version of the talk Lambda: The Ultimate Dependency Injection Framework in YOW 2012. In 2013, Jason Arhart wrote Scrap Your Cake Pattern Boilerplate: Dependency Injection Using the Reader Monad, which I’m going to base my example on.

Imagine we have a case class for a user, and a trait that abstracts the data store to get them.

``````scala> :paste
// Entering paste mode (ctrl-D to finish)
case class User(id: Long, parentId: Long, name: String, email: String)
trait UserRepo {
def get(id: Long): User
def find(name: String): User
}

// Exiting paste mode, now interpreting.
defined class User
defined trait UserRepo``````

Next we define a primitive reader for each operation defined in the `UserRepo` trait:

``````scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Users {
def getUser(id: Long): UserRepo => User = {
case repo => repo.get(id)
}
def findUser(name: String): UserRepo => User = {
case repo => repo.find(name)
}
}

// Exiting paste mode, now interpreting.
defined trait Users``````

That looks like boilerplate. (I thought we are scrapping it.) Moving on.

Based on the primitive readers, we can compose other readers, including the application.

``````scala> :paste
// Entering paste mode (ctrl-D to finish)
object UserInfo extends Users {
def userInfo(name: String): UserRepo => Map[String, String] =
for {
user <- findUser(name)
boss <- getUser(user.parentId)
} yield Map(
"name" -> s"\${user.name}",
"email" -> s"\${user.email}",
"boss_name" -> s"\${boss.name}"
)
}
trait Program {
def app: UserRepo => String =
for {
fredo <- UserInfo.userInfo("Fredo")
} yield fredo.toString
}

// Exiting paste mode, now interpreting.
defined object UserInfo
defined trait Program``````

To run this `app`, we need something that provides an implementation for `UserRepo`:

``````scala> :paste
// Entering paste mode (ctrl-D to finish)
val testUsers = List(User(0, 0, "Vito", "vito@example.com"),
User(1, 0, "Michael", "michael@example.com"),
User(2, 0, "Fredo", "fredo@example.com"))
object Main extends Program {
def run: String = app(mkUserRepo)
def mkUserRepo: UserRepo = new UserRepo {
def get(id: Long): User = (testUsers find { _.id === id }).get
def find(name: String): User = (testUsers find { _.name === name }).get
}
}
Main.run

// Exiting paste mode, now interpreting.
testUsers: List[User] = List(User(0,0,Vito,vito@example.com), User(1,0,Michael,michael@example.com), User(2,0,Fredo,fredo@example.com))
defined object Main
res3: String = Map(name -> Fredo, email -> fredo@example.com, boss_name -> Vito)``````

We got the boss man’s name.

We can try using `actM` instead of a `for` comprehension:

``````scala> :paste
// Entering paste mode (ctrl-D to finish)
object UserInfo extends Users {
def userInfo(name: String): UserRepo => Map[String, String] =
actM[UserRepo => ?, Map[String, String]] {
val user = findUser(name).next
val boss = getUser(user.parentId).next
Map(
"name" -> s"\${user.name}",
"email" -> s"\${user.email}",
"boss_name" -> s"\${boss.name}"
)
}
}
trait Program {
def app: UserRepo => String =
actM[UserRepo => ?, String] {
val fredo = UserInfo.userInfo("Fredo").next
fredo.toString
}
}
object Main extends Program {
def run: String = app(mkUserRepo)
def mkUserRepo: UserRepo = new UserRepo {
def get(id: Long): User = (testUsers find { _.id === id }).get
def find(name: String): User = (testUsers find { _.name === name }).get
}
}
Main.run

// Exiting paste mode, now interpreting.
defined object UserInfo
defined trait Program
defined object Main
res4: String = Map(name -> Fredo, email -> fredo@example.com, boss_name -> Vito)``````

The code inside of the `actM` block looks more natural than the `for` version, but the type annotations probably make it more difficult to use.

That’s all for today.