gpt4 book ai didi

scala - 如何使用单片眼镜修改嵌套 map 和scala中的另一个字段

转载 作者:行者123 更新时间:2023-12-01 13:39:35 24 4
gpt4 key购买 nike

我第一次尝试单片眼镜。

这是案例类:

case class State(mem: Map[String, Int], pointer: Int)

我想使用标准 scala 进行当前修改:

def add1 = (s: State) => s.copy(
mem = s.mem.updated("a", s.mem("a") + 1),
pointer = s.pointer + 1
)

这是我用单片眼镜实现的

val mem = GenLens[State](_.mem)
val pointer = GenLens[State](_.pointer)
val add2 = (mem composeLens at("a")).modify(_.map(_ + 1)) andThen pointer.modify(_ + 1)

不幸的是,代码并不清晰......

  1. 有没有更简洁的方式?
  2. 我们可以用宏生成所有样板文件吗?

[更新] 我想出了一个组合器

  def combine[S, A, B](lsa : Lens[S, A], f: A => A, lsb: Lens[S, B], g: B => B) : S => S = { s =>
val a = lsa.get(s)
val b = lsb.get(s)
val s2 = lsa.set(f(a))
val s3 = lsb.set(g(b))
s2(s3(s))
}

问题是我还需要产生一个中介和无用的S。

[update2] 我已经清理了组合器的代码。

  def mergeLens[S, A, B](lsa : Lens[S, A], lsb : Lens[S, B]) : Lens[S, (A, B)] =
Lens.apply[S, (A, B)](s => (lsa.get(s), lsb.get(s)))(t => (lsa.set(t._1) andThen lsb.set(t._2)))

def combine[S, A, B](lsa : Lens[S, A], f: A => A, lsb: Lens[S, B], g: B => B) : S => S = {
mergeLens(lsa, lsb).modify { case (a, b) => (f(a), g(b)) }
}

最佳答案

您可以使用 index 而不是 at 来获得稍微短一点的版本:

(mem composeOptional index("a")).modify(_ + 1) andThen pointer.modify(_ + 1)

但是,如果两个 Lens 指向同一视场,mergeLens 也称为水平合成不满足 Lens 定律:

  import monocle.macros.GenLens

case class Person(name: String, age: Int)
val age = GenLens[Person](_.age)

val age2 = mergeLens(age, age)
val john = Person("John", 25)
age2.get(age2.set((5, 10))(john)) != (5, 10)

关于scala - 如何使用单片眼镜修改嵌套 map 和scala中的另一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41410854/

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