gpt4 book ai didi

scala - Scala 中依赖注入(inject)的读者组成

转载 作者:行者123 更新时间:2023-12-05 00:11:01 27 4
gpt4 key购买 nike

这是一个简单的服务示例,其方法返回 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 我必须在参数列表中有 map :
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.s2f2Service1_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
}))

问题是,有没有更好的方法?或者至少是语法?因为有几个级别的依赖,它看起来会很奇怪。

最佳答案

我可能会“取消”读者,这样我就没有两层(或更多)读者,而是有一个 n 元组作为环境。然后,您可以使用 local 将较小的读者“提升”到当前水平。 .

例如,而不是 Reader[Service1_1, Reader[Map[String, Int], Int]]我会使用 Reader[(Service1_1, Map[String, Int]), Int] :

import cats.data.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 {
type Env = (Service1_1, Map[String,Int])

def s2f2(i: Int): Reader[Env, Int] =
for {
s <- Reader((_: Env)._1)
r1 <- s.s1f1.local((_: Env)._2)
r2 <- s.s1f2.local((_: Env)._2)
} yield r1 + r2 + i
}

进而:
scala> object s1 extends Service1_1
defined object s1

scala> object s2 extends Service1_2
defined object s2

scala> s2.s2f2(2).run((s1, Map("age"-> 1, "name"-> 2)))
res0: cats.Id[Int] = 5

这与您的 s2f2 完全相同。除了不是 s2.s2f2(2).run(s1).run(myMap)我们写 s2.s2f2(2).run((s1, myMap)) ,甚至只是 s2.s2f2(2).run(s1, myMap)使用适应的参数。

这种方法的优点是,即使您添加了层,您也可以在一个 for 中组合新的和以前的阅读器。 -通过 local理解.

关于scala - Scala 中依赖注入(inject)的读者组成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55137404/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com