Вот пример простого сервиса, методы которого возвращают читатель:
trait Service1_1{
def s1f1:Reader[Map[String,Int],Int] =
Reader(_("name"))
def s1f2:Reader[Map[String,Int],Int] =
Reader(_("age"))
}
Вот сервис-потребитель, который принимает параметр, карту, а также возвращает сам читатель:
trait Service1_2 {
def s12f1(i:Int, map:Map[String,Int]):Reader[Service1_1, Int] =
Reader(s => {
val r = for {
r1 <- s.s1f1
r2 <- s.s1f2
} yield r1 + r2
r.run(map) + i
})
}
Хорошо, чтобы использовать Service1_2.s12f1, у меня должна быть карта в списке параметров:
object s1 extends Service1_1
object s2 extends Service1_2
val r = s2.s12f1(3, Map("age"-> 1, "name"-> 2)).run(s1)
Вопрос: как реализовать Service1_2.s12f2
:
trait Service1_2 {
def s2f2 = ???
}
Чтобы иметь возможность запускать его так:
s2.s2f2(2)
.run(s1)
.run(Map("age"-> 1, "name"-> 2))
Основная идея — отложить передачу зависимости до исполнения. Это должно позволить получить лучшую композицию и отложенное исполнение. Как заставить его работать? Каковы наилучшие методы работы с Readers, если есть вложенные вызовы с такими зависимостями. Например, представьте сервис Service1_3
, который в одном методе будет использовать как Service1_2.s2f2
, так и Service1_1.s1f1
.
ОБНОВЛЕНИЕ, хорошо, я мог бы это реализовать, но это выглядит слишком сложно:
def s2f2(i:Int): Reader[Service1_1, Reader[Map[String,Int],Int]] =
Reader(s => Reader(map => {
val r = for {
r1 <- s.s1f1
r2 <- s.s1f2
} yield r1 + r2
r.run(map) + i
}))
Вопрос, есть ли лучший подход? Или хотя бы синтаксис? Потому что с несколькими уровнями зависимости это будет выглядеть странно.