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 g
tripleToString: Int => String = <function1>
scala> tripleToString(2) res0: String = 6
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
val g = f map (i => i + 2)
val h = for (i <- g) yield i.toString
trait Users {
def getUser(id: Int) = Reader((userRepository: UserRepository) =>
userRepository.get(id)
)
def findUser(username: String) = Reader((userRepository: UserRepository) =>
userRepository.find(username)
)
}
I'm gonna return a User, when I get a UserRepository
The actual injection is deferred
object UserInfo extends Users {
def userEmail(id: Int) = { getUser(id) map (_.email) } def userInfo(username: String) = for { user <- findUser(username) boss <- getUser(user.supervisorId) } yield Map( "fullName" -> s"${user.firstName} ${user.lastName}", "email" -> s"${user.email}", "boss" -> s"${boss.firstName} ${boss.lastName}" )
}
but we don't have to mention the Repository anywhere except our primitive Readers
trait Repositories {
def userRepository: UserRepository
def questionRepository: QuestionRepository
}
trait Users {
def getUser(id: Int) = Reader((repos: Repositories) =>
repos.userRepository.get(id)
)
}
object Application extends Application(UserRepositoryImpl)
class Application(userRepository: UserRepository) with Users {
def getUserEmail(id: Int) = Action {
HttpOk(UserInfo.userEmail(id)(userRepository))
}
}
object Application extends Application with UserRepositoryComponentImpl
trait Application extends Controller with Users {
this: UserRepositoryComponent =>
def getUserEmail(id: Int) = Action {
HttpOk(UserInfo.userEmail(id)(userRepository))
}
}