Considering that someLabels is of type Map[String, String], your code is either excessive or just supplies wrong argument to composed Optional. If we simplify signature of composeOptional method in Lens[S, A], it yields:
def composeOptional(other: Optional[A, B]): Optional[S, B]
Optional[A, B], at the very imprecise approximation, corresponds to indirection that allows to:
- look into value of type
A and get its component of type B (or A itself if it's missing);
- build a new object of type
A by replacing its component of type B (or just return original object if there's no such component).
labels composeOptional index("app") yields Optional[Metadata, String]. That obviously won't work on Map[String, String]: it indirects from Metadata to Map[String, String] (via labels) and then immediately from Map[String, String] to its String element (via index("app")), hiding map access from the user entirely. If you're trying to just set a value at a given key in someLabels map, it suffices to use 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")
Your composed Optional, on the other hand, works over 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")
I've checked it with following versions (in 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"
)