Scala 使用Monocle更新嵌套贴图的正确语法
我已经看到了更新Scala 使用Monocle更新嵌套贴图的正确语法,scala,monocle-scala,Scala,Monocle Scala,我已经看到了更新地图的方法,但是语法有问题 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) 我想更新标签地图中的按键“app”。但我无法编译以下内容: (la
地图的方法,但是语法有问题
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)
我想更新标签
地图
中的按键“app”。但我无法编译以下内容:
(labels.composeOptional(index("app"))).set("whatever")(someLabels)
事实上,Monacle的一位作者的这篇文章没有编译。如果没有事件类的定义,我没有一个确切的答案,但是在大学的例子中,我能够用本文撰写时的最新版本monocle 1.5.0-cats-M1更新嵌套地图。确保在您的项目中同时具有单片眼镜核心和单片眼镜宏JAR。那么
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包装成与使用键从映射检索值进行访问时的选项返回类型相对应的部分 考虑到someLabels
属于Map[String,String]
类型,您的代码要么过多,要么只是为组合的可选提供了错误的参数。如果我们简化Lens[S,A]
中composeOptional
方法的签名,它将产生:
def composeOptional(other: Optional[A, B]): Optional[S, B]
可选[A,B]
在非常不精确的近似值下,对应于允许以下操作的间接寻址:
- 查看类型
A
的值,并获取其类型B
的组件(或者如果缺少A
本身)李>
- 通过替换
B
类型的组件来构建a
类型的新对象(如果没有此类组件,则只返回原始对象)
标签组合可选索引(“app”)
产生可选[元数据,字符串]
。这显然不适用于Map[String,String]
:它从Metadata
到Map[String,String]
(通过labels
),然后立即从Map[String,String]
到它的String
元素(通过index(“app”)
),完全隐藏对用户的地图访问。如果您试图在someLabels
map中的给定键处设置一个值,那么使用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")
另一方面,您编写的可选
,可用于元数据
:
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
中)检查了它:
什么是someLabels
?合成镜头是从元数据
到索引“app”
处的标签
映射元素的间接指向,因此一些标签
应该是元数据
@P.Frolov类型。这是一个映射[String,String]
我使用quicklens,因为我的使用量非常少,不值得费力地解决这些问题。单片眼镜还带来了很多依赖性(Scalaz、Shapess),这对我来说又是过分了。我以后再玩,如果你的回答对我有效,我就接受你的回答。在那之前,请考虑将投票作为赞赏的象征。AbjjiTrackar只有MunoCLE通用模块依赖于无形状的,我不认为您使用它。Scalaz或cats是core中唯一的依赖项,如果您想在scala中执行fp,它是必需的。
scalaVersion := 2.12.3
libraryDependencies ++= Seq(
"com.github.julien-truffaut" %% "monocle-core" % "1.4.0",
"com.github.julien-truffaut" %% "monocle-macro" % "1.4.0"
)