这是一个简单的服务示例,其方法返回 reader:
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))
主要思想是推迟将依赖传递给执行。这应该允许获得更好的组合和延迟执行。如何让它工作?阅读器的最佳实践是什么,以防存在具有此类依赖关系的嵌套调用。例如,想象一下服务,Service1_3
它在一种方法中将同时使用Service1_2.s2f2
和Service1_1.s1f1
UPDATE,好的,我可以实现它,但它看起来过于复杂:
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
}))
问题是,有没有更好的方法?或者至少是语法?因为有几个级别的依赖,它看起来会很奇怪。