Hacker News new | ask | show | jobs
by chowells 350 days ago
I strongly recommend using the lens operators. They are uniformly named such that you can trivially identify their behavior based on their lexical construction, and using them reduces mental parsing overhead significantly.

For the former assertion: ^. means "get a single result". ^.. means "get multiple results". ^? means "get zero or one result". ^@.. means "get multiple results, along with their indices". <<|>~ means "modify a value by combining the target with the |> operator from Snoc, then return a tuple of the old target value and the full structure including the combined value". There is a tiny language in the pattern of operator names, and it's worth the 3 minutes of work it takes to learn it.

And as a reward for learning it, you get to write expressions with far fewer parentheses. This is a massive win. Parenthesized expressions introduce a miserable minigame during reading, where you have to properly match each paren to its correct partner keeping a mental stack to handle nesting. By contrast, the lens operators give you the far simpler mental parsing task of separating the optic, the input, and the operation on the input. There's no nesting involved. The process is a simple visual scan that doesn't require keeping a mental stack. It's a lot easier to quickly read and comprehend.

About the only thing you lose is the ability to easily read code out loud. I don't limit myself to thinking in sounds, but I guess for some people it's important to communicate code out loud. For those kinds of pedagogical purposes, I guess it's ok to pass on the operators. But for code I'm going to work with over a long period of time I'd much rather have the readability advantages of the operators.

3 comments

Having fewer parentheses is not a win, it makes more things implicit and forces everyone to remember operator precedence. In my opinion operator precedence is never worth remembering other than plus minus multiply and divide.

I find heavily parenthesized expressions easy to read, just because I tend to break them into multiple lines and the indentation serves as a guide. Don't put too many of them on a single line.

That might be a strong argument in many languages, but in Haskell you really don't need to memorize operator precedence. In nearly every case, the types tell you the precedence. They don't literally, but most expressions only type check in one particular parse tree.

As a result, you just don't think about precedence when reading code. If you assume the code type checked correctly, you know that it all just makes sense. You don't need to create a parse tree. You just trust.

(Actually, this is the huge advantage of Haskell in most every case. You don't need to understand everything. You just trust that it does what makes sense, and you're right. The compiler enforces it.)

You may want to check out J as a language. It is wonderfully terse and allows for point-free programming, and has all of the advantages you point to above.
couldn't find/replace be used to swap between operators and readable function names?