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"
)