Entropic Thoughts logo

Entropic Thoughts

Subscribe
Archives
April 23, 2025

The greatest procedural language in the world, and some obfuscation of it

We learn in what sense Haskell is the greatest procedural language in the world, and we debate whether or not to abstract over functions.

Hello! I hope your week is going well.

New articles

Haskell: A Great Procedural Language

Haskell is sometimes claimed to be the best procedural language in the world. It is unclear to beginners what this means, since Haskell is decidedly functional. Haskell can be used to program in a procedural style, and it is indeed very good at it – in some ways, better than many procedural languages.

This article looks at some examples of things Haskell does well, all based on the fact that side effects are first-class values in Haskell, with functions that operate over them. This allows us to refactor procedural code more fearlessly than in procedural languages, and it allows us to clarify our intention with specialised control structures/objects like sequencing and replicating effects, building stateful traversals, etc.

Despite being technical, the article is meant to be readable even without much exposure to Haskell.

Full article (20–40 minute read): Haskell: A Great Procedural Language

Flashcard of the week

Surprisingly often when looking for a way to simplify a definition in code, I end up in the Control.Arrow library. I don't yet know exactly what arrows are, but I think they abstract over computations somehow, and I think they are more fundamental and important than people let on.

I have started reading a little about arrows on and off, and I am getting more of an intuition for them. One of the things that brought home the point for me was the following question. It has nothing to do with arrows, but the intuition carries over rather well for me.

What does liftA2 op f g mean when f and g are functions?

This is easy to figure out by looking at the instance of applicative for functions, but I have it as a flashcard in order to quickly recognise the idiom when it shows up in code.

Evaluate op (f x) (g x), i.e. split x into a pair, apply f and g to respective half, then recombine with op.

The way this ties into arrows is that if we have liftA2 (,) f g, i.e. we want to get the tuple (f x, g x), we can use the arrow instance of functions instead and write it more succinctly as f &&& g. The &&& arrow operator is the split-into-a-pair-and-apply-different-functions-to-either-side operation, without the final recombining step implied by liftA2.

I'm not yet entirely sure it is a good idea to use these things in production code because abstractions over functions tend to be hard to read for beginners, but the more I read about them, the more I'm sold that it's useful at least to be familiar with the idea of abstracting over functions.

Premium newsletter

The next premium newsletter is in the making! It will contain the usual, and a review of Code That Fits in Your Head: Heuristics for Software Engineering. If you're interested, a premium subscription is currently only $2/month, cancelable at any time, no questions asked.

That money also gets you the past issues, including the most recent one, which has a list of the 20 best books I've read, along with brief summaries, and pointers on how to make such a list of your own. (It's harder than it sounds.)

To upgrade, click the subscription link at the top of this newsletter and fill in your email again.

Your opinions

I cannot improve without feedback. Reply to this email to share your thoughts on any of the topics above, or anything else!Hello! I hope your week is going well.

Don't miss what's next. Subscribe to Entropic Thoughts:
custom
This email brought to you by Buttondown, the easiest way to start and grow your newsletter.