ekmett / lens

Lenses, Folds, and Traversals - Join us on web.libera.chat #haskell-lens
http://lens.github.io/
Other
2.03k stars 272 forks source link

Replacer? #72

Closed pthariensflame closed 11 years ago

pthariensflame commented 11 years ago

Setters are capable of replacing the target value(s) because they are capable of modifying the target value(s). Modification always allows replacement as a special case (via const and its ilk), but you cannot generate modification from solely replacement (if you have both replacement and retrieval, you can, but then you just end up with a Traversal).

This seems to hint at a supertype of Setter: Replacer (plus Indexed and/or Simple variants, of course). Essentially:

I've come up with a couple of encodings for Replacer that try to fit within the van Laarhoven model, and I'd like to generate some discussion of this. It's not critical to me, but it is an interesting hole in the current design space.

pthariensflame commented 11 years ago

One particular use for Replacer where Setter is unusable is with existential data constructors, especially those with multiple fields. Then it might not make sense to map over those values; you could only replace them blindly.

ekmett commented 11 years ago

The problem with both of the Replacer variants is that they don't fit the composability model that everything else does. -- You can't compose them.

I mentioned them in my 'Mirrored Lenses' post on comonad.com. (This is what I originally called a Setter actually, back when I called what I now call a Setter a Modifier)

I dropped them from the system because of the lack of composability.

Since the rank 3 type basically means you wind up wallowing in type signatures, the lack of composability means you don't get to mix them well with other lens types, and the fact that they generally lack laws, I'm not in a hurry to put them back into the hierarchy.

ekmett commented 11 years ago

Closing this out as wontfix for now. I might be convinced to re-open it, but the lack of composability, and violation of all of the laws that I've tried to preserve everywhere else leads me to believe these don't bring enough to the table to warrant the explanation of their role, and the type inference or explicit conversion headaches they introduce elsewhere.

Lev135 commented 1 year ago

For those, who will read this like me. For setting-only operation you can just use Setter s t () b (it's actually isomorphic to b -> s -> t, though definitions of Replacer above are not -- we should use unit type instead of Void). So

type Replacer s t b  = Setter s t () b

replacer :: (b -> s -> t) -> Replacer s t b
replacer h fb = setting (h . ($ ())) fb

-- and standard 'set' operation works fine with it
ekmett commented 1 year ago

You can write that down, but it doesn't compose or comply with the laws presented in the original Mirrored Lenses post. Ultimately, the a and the b should be related by the same substitution that relate s and t, in your Replacer, they are unrelated.

The lens library doesn't preclude you from using such a beast, but it is not a lawful optic, and you have to reason case-by-case, combinator-by-combinator, to see if it does what you want as you go.

Your mileage may vary. Caveat emptor. Here be dragons, etc.