Search code examples
haskelllenses

unlawful lens Haskell


Is there a common name/type for a lens-like object that does not satisfy the property of getting out what you put in? For example something like a listLength :: Lens [a] Int where if you put in a length shorter than that of the source list you get a shortened list, but if you put in a longer length the original length is preserved.


Solution

  • A lens is not just a function with the type forall f. Functor f => (a -> f b) -> s -> f t — it's a function with that type that obeys certain laws. In particular, (as documented in the lens docs):

    1. You get back what you put in,
    2. Putting back what you got doesn't change anything, and
    3. Setting twice is the same as setting once.

    If your function doesn't obey those laws, then it's just a function with a type that's similar to a lens.

    In your particular example, listLength breaks the first and third laws, so it's not a lens. That said, it would work just fine as a Getter, which I think is the only principle thing we can say about it.


    More generally, it doesn't really make sense to ask about things that lack laws, as things tend to be defined by what laws they obey rather than what they don't obey. For example, I pointed out that listLength makes a perfectly good Getter because it consistently extracts a value out of the [a] input.

    So, I'll ask you: What distinguishes it from a function listZero :: Lens [a] Int that always emits 0? Can you come up with a general law that listLength obeys that listZero doesn't? If so, then you have something to actually look for in the current literature: that is, listLength is one of a set of functions that obeys some (possibly interesting) law. If not, then you just have a function with a type that makes it look like a lens.