Marshall Bowers

Conjurer of code. Devourer of art. Pursuer of æsthetics.

Programs as Lego Structures

Thursday, November 11, 2021
585 words
3 minute read

As a child, I was very much a Lego enthusiast. My brother and I had these massive tubs filled with Lego bricks and minifigs. Much to our mother's dismay, we would dump everything out on the floor of our bedroom and spread the pieces out. After all, it's much easier to find that exact piece you're hunting for with everything in sight. The alternative, of course, being rummaging blindly through a thirty gallon storage bin.

When you spend as much time as I did working on new builds, you start to gain a familiarity with the pieces you have at your disposal. While working on a structure, I'd realize that I needed that one piece to get the outcome I desired.


Fast-forward to now and I still find myself in a similar situation to those days spent sifting through Lego bricks on my bedroom floor. Only now instead of building castles I'm building computer programs.

I prefer to write my code in a functional style, which, if you squint a little, bears a striking resemblance to working with Legos.

In functional programming, functions are your bricks.

Just as each brick has its own shape, so do functions have their own shape. Likewise, just as Lego bricks lock together to form a cohesive structure, so too can you compose functions together to form a complete program.

As you write programs in this style, you start to see where certain "bricks" fit in. For instance, when writing a PureScript program I may find myself faced with the following hole:

? :: forall a. Array (Maybe a) -> Array a

What function would slot in here?

Having seen this shape before enough times, I know that the function needed is Array.catMaybes.

But suppose you didn't know that offhand. How would you find the function that fits this slot? If we were still talking about Legos, you would have to go panning through bins to find the right piece. If you were desperate, you might event head over to the Pick a Brick page on the Lego website to search for (and buy) the piece that you need.

Conveniently enough, we can do the same thing here. Plugging the function signature into Pursuit's search will reveal that Array.catMaybes is the function we need.

If we were writing Haskell, Hoogle can be used in the same fashion.

Programming in this fashion can be incredibly powerful. Do it for long enough and you'll start to develop an intution for when the function you need already exists1, all you need to do is find it.


An interesting property of Legos is this:

you never make your own Lego bricks.

Let that sink in.

You never make your own Lego bricks, yet you can still build all sorts of fantastic creations.

The reason for this is rather simple: Lego provides incredibly good primitives for you to use. These building blocks2 provide enough power and variety to assemble them in all sorts of ways to fit any situation you can think of.

The functional paradigm has a lot of excellent primitives. The concepts pulled from category theory—functors, semigroups, applicatives, you name it—are all highly general and widely applicable.

It makes me wonder: what sort of programs can be built given enough good primitives?

1

traverse, it's always traverse.

2

No pun intended.