我看到更新Map
的{{3}},但我的语法有问题。
val pod: Lens[Event, Pod] = GenLens[Event](_.`object`)
val metadata: Lens[Pod, Metadata] = GenLens[Pod](_.metadata)
val labels: Lens[Metadata, Map[String, String]] = GenLens[Metadata](_.labels)
我想更新labels
Map
中的关键“应用”。但我无法得到以下内容进行编译:
(labels.composeOptional(index("app"))).set("whatever")(someLabels)
事实上,Monacle的一位作者的这个official example没有编译。
答案 0 :(得分:3)
如果没有Event类的定义,我没有确切的答案,但是following the tutorial和大学示例,我能够在撰写本文时使用最新版本更新嵌套Map,monocle 1.5。 0-猫-M1。确保您的项目中同时具有单片核心和单片宏。然后,
import monocle.macros.GenLens
import monocle.function.At.at // // to get at Lens
import monocle.std.map._ // to get Map instance for At
然后,按照大学的例子,
case class Lecturer(firstName: String, lastName: String, salary: Int)
case class Department(budget: Int, lecturers: List[Lecturer])
case class University(name: String, departments: Map[String, Department])
val departments = GenLens[University](_.departments)
val uni = University("oxford", Map(
"Computer Science" -> Department(45, List(
Lecturer("john" , "doe", 10),
Lecturer("robert", "johnson", 16)
)),
"History" -> Department(30, List(
Lecturer("arnold", "stones", 20)
))))
我能够
(departments composeLens at("History")).set(Some(Department(30, List(Lecturer("arnold", "stones", 30)))))(uni)
与上面代码的主要区别在于使用at()并将Department包装为Some,以便在使用键从Map检索值进行访问时与Option返回类型相对应。
答案 1 :(得分:0)
考虑到someLabels
的类型为Map[String, String]
,您的代码要么过多,要么仅为组合Optional
提供错误的参数。如果我们在composeOptional
中简化Lens[S, A]
方法的签名,则会产生:
def composeOptional(other: Optional[A, B]): Optional[S, B]
Optional[A, B]
,在非常不精确的近似下,对应于允许的间接:
A
类型的值并获取其B
类型的组件(如果缺少,则为A
本身); A
类型的组件来构建类型为B
的新对象(如果没有这样的组件,则只返回原始对象)。 labels composeOptional index("app")
会产生Optional[Metadata, String]
。这显然不适用于Map[String, String]
:它从Metadata
到Map[String, String]
(通过labels
),然后立即从Map[String, String]
到String
。 } element(通过index("app")
),完全隐藏用户的地图访问权限。如果您只想在someLabels
地图中的给定键设置值,则只需使用index
:
val someLabels1 = Map("app" -> "any")
val someLabels2 = Map("unit" -> "any")
index("app").set("whatever")(someLabels1) // Map("app" -> "whatever")
index("app").set("whatever")(someLabels2) // Map("unit" -> "any")
另一方面,您的撰写Optional
适用于Metadata
:
case class Metadata(labels: Map[String, String])
val someLabels = Map("app" -> "any")
val meta = Metadata(someLabels)
(labels composeOptional index("app")).set("whatever")(meta)
// Metadata(Map("app" -> "whatever")
我已使用以下版本(build.sbt
)检查了它:
scalaVersion := 2.12.3
libraryDependencies ++= Seq(
"com.github.julien-truffaut" %% "monocle-core" % "1.4.0",
"com.github.julien-truffaut" %% "monocle-macro" % "1.4.0"
)