← Back to context

Comment by eru

12 hours ago

I have almost the opposite view: tail calls are great.

But most of the time you will want to express your program in terms of more restricted combinators, because restriction makes the readers job easier. Easier to understand, and easier to convince yourself that no weird things are happening.

Basically, you might already agree that restricting mutation is good. This is the same principle.

So when you see a 'fold' you know even without looking at the callback, that your program will run through the whole list and not exit early. When you see a 'map' you also know that no early exit will happen, but even more you know exactly how the return value will be constructed (whereas for fold that's arbitrary).

However you are right that 'fold' and 'filter' and 'map', just like 'for' and 'while', are not good as universal building blocks.

That's why you should define new combinators when you need them. Typically, that's when you define new data structures, eg when you define a tree you will also want to define a 'map' for it, and also various tree traversals and perhaps searches. Less typically, you also want new combinators for new algorithmic ideas, even on old data structures.

Eg matrix multiplication is an interesting combinator. You provide the meaning of 'addition' and 'multiplication' as call-backs, and depending on your choice you get an algorithm for finding shortest paths or for matching regular expressions etc (in addition to the obvious matrix-multiplication on real numbers, of course). See https://news.ycombinator.com/item?id=43076088 for the former.

I learned recursion in Pascal and had a ball implementing innumerable algorithms purely in recursive structures. The code was often more compact and simpler to explain — once you understood induction. I agree that combinators are helpful, but they’re not universal. Anyway, we’re probably violently agreeing.

  • Yes, Pascal (as least the version I know) weren't exactly friendly to passing around first class functions. It might be possible, but it ain't pretty.

    I'm not sure Pascal does closure well?

    A combinator heavy style works best in a language (and ecosystem) that welcomes it, like eg Haskell.