The process my brain goes through when programming...
And now to prove the point of the diagram...
A task I've come across several times while programming is taking a list describing a template, and completing it with input from elsewhere.
Let me describe further (this post is a literate Haskell file...)
For example, the list:
describes a template, where the first and third elements are fixed, but the remaining (second, fourth and fifth) elements come from external input.
So if testTemplate was used with the following filling...
The result we expect would be:
So we need to implement a function of type [Maybe String] -> [String] -> [String], and it should make our test give back True.
Now the most explicit way to do this is to use pattern matching, and just work through the cases on the template list...
Thing is, I rarely ever use explicit pattern matching nowadays (especially when it comes to lists and maybe), as there are a whole host of combinators that do it for you. Also using combinators over pattern matching can make your code a lot more readable. And anyways, explicitly writing out the recursion fills me with an ill feeling.
So what are we to do? Well one trick is to notice that the filling is actually some state in the algorithm. For each template element, we peel the next element off the state or just carry it across, depending on whether the template element is Nothing or Just.
Well that's concise-ish, and (assuming you know the standard libraries) is quite clear / reads well. Of course getNext's definition is a bit verbose, but it's hidden by a meaningful name.
But wait, there's more! If you stare at getNext for a while, with the definition of State next to it, you'll realise that State (\(h:tl) -> (h,tl)) does the same thing. So we can rewrite inlining getNext and using arrow combinators instead of the explicit lambda...
Arn't we clever? Possibly too clever, while it is a 1-liner, it doesn't (to me) read like psuedo-english. I'd probably use something like this in reality, as (I think) it reads slightly better.
So there you have it, how to spend at least an hour and a half blogging about how you can simplify a 3 line haskell function down to one line, and then realising that a different 3 line function reads better if you know lots of esoteric parts of the Haskell standard libraries. At least I havn't tried to write a monad tutorial...