TL;DR: given a functional-reference/optics library, should you be able to say "set the endpoint of this path to X, creating empty elements along the way as necessary"?
Scala and Elm have a lens implementation libraries (Scala, Elm). They add an Optional to the canonical Lens/Prism/Iso types. It's useful for dictionaries/maps/hashes. I think it corresponds roughly to Haskell/Lens's Lens.At. I have a question about the behavior of Elm's version that seems Not What You'd Want, but can't interpret the Haskell or Scala versions well enough to determine an answer from them.
The issue is composing two Optional values together. Suppose we have two Optionals that focus on particular keys in a dictionary:
topis an Optional that follows a"one"key if it exists. (It returns eitherJust the-value-for-the-keyorNothing.)bottomis an Optional that follows a"two"key if it exists.
Importantly, if you set a key that doesn't exist, both of them add it. Here's an example:
> import Monocle.Optional as Opt
> import Monocle.Common as Common
> top = Common.dict "one"
> top.set 3 Dict.empty
Dict.fromList [("one",3)] : Dict.Dict String numberHowever, consider the case if you compose the two Optionals:
> bottom = Common.dict "two"
> composed = Opt.compose top bottomAs you'd expect, if you use the composed Optional on a structure whose "one" key points to an empty Dict, that dict gets updated:
> > composed.set "new!" (Dict.singleton "one" Dict.empty)
{"one" : {"two" : "new!"}}(I used a literal map notation to make the result clearer.)
Great. But if I use that composed Optional on a Dict that's entirely empty, it just fails:
> composed.set "new!" Dict.empty
{}I can see an argument that it should fail, rather than producing {"one" : {"two" : "new!"}}. However, silently doing a different thing depending on whether it's a composed Optional or not seems like asking for trouble.
I understand (I think) the motivation: I can't see a way to implement the behavior I'd want without creating an Optional with a "create an empty structure" function. And I haven't worked through how that would affect composing with prisms or lenses.
I'm looking for people to say either "that behavior makes sense because " or "that's a (perhaps unavoidable) weakness of the Elm version (or all versions)."