Monads and Macros

There are two techniques in software development that have an almost gnostic mystique about them: monads and macros.

Macro burrito

The photo is a pun [1].

Pride and pragmatism

As with everything people do, monads and macros are used with mixed motives, for pride and for pragmatism.

As for pride, monads and macros have just the right barrier to entry: high enough to keep out most programmers, but not so high as to be unsurmountable with a reasonable amount of effort. They’re challenging to learn, but not so challenging that you can’t show off what you’ve learned to a wide audience.

As for pragmatism, both monads and macros can be powerful in the right setting. They’re both a form of information hiding.

Monads let you concentrate on functions by providing a sort of side channel for information associated with those functions. For example, you may have a drawing program and want to compose a rotation and stretching. These may be ostensibly pure functions, but they also effect a log of operations that lets you undo actions. It would be burdensome to consider this log as an explicit argument passed into and returned from every operation. so you might keep this log information in a monad.

Macros let you hide the fact that your programming language doesn’t have features that you would like. Operator overloading is an example of adding the appearance of a new feature to a programming language. Macros take this much further, for better or for worse. If you think operator overloading is good because of its potential to clarify code, you’ll like macros. If you think operator overload is bad because of its potential for misuse, you definitely won’t like macros.

Mutually exclusive

Few people are excited about both monads and macros; only one person that I know comes to mind.

Monads and macros appeal to opposite urges: the urge to impose rules and the urge to get around rules. There is a time for both, a time to build structure and a time to tear structure down.

Monads are most popular in Haskell, and macros in Lisp. These are very different languages and their communities have very different values [2].

The ideal Haskell program has such rigid structure that only correct code will compile. The ideal Lisp program is so flexible that it is essentially a custom programming language.

A Haskell programmer would like to say that a program is easy to reason about because of its mathematical structure. A Lisp programmer would like to say a program is easy to read because it maps well onto the problem at hand.

Lisp enthusiast Doug Hoyte says in his book Let Over Lambda

As we now know, nobody truly understands macros.

A Haskell programmer would find this horrifying, but a Lisp programmer would consider it an acceptable price to pay or even something fun to explore.

Related posts

[1] “Giant veggie burrito” by dphiffer is licensed with CC BY 2.0. It’s a macro burrito. There are myriad monad metaphors, including famously one saying a monad is a burrito.

[2] Here I’m referring to archetypes, generalizations but not exaggerations. Of course no language community is monolithic, and an individual programmer will have different approaches to different tasks. But as a sweeping generalization, Haskell programmers value structure and Lisp programmers value flexibility.

4 thoughts on “Monads and Macros

  1. I love learning things from young programmers. One of them replaced an elaborate monadic system I had built in Python (using the o-slash library) with good-ol’-decorators! She obviously figured out what I was doing and replaced it with something she found more understandable.

    Henceforth, I haven’t found anything that I want to do with monads in Python that I cannot do more idiomatically with decorators! Decorators are the tortilla wrapping the burrito!

  2. Nice analysis! Something I’d love to see is a study of programming language communities focusing on (1) what they value and (2) what kinds of problems they like to work on. My hope is that such a study would illustrate to everyone that the world of software is much too big for any one point of view to be the “best” one, and that different languages are complementary rather than in competition. The conclusion would then be that we need different language communities to cooperate, in order to make large-spectrum software systems possible.

    Having disqualified myself from conducting such a story by having written my conclusion, I can now only hope that someone will take it up to prove me wrong!

  3. A macromonad is a bacterium of the genus Macromonas. I spent a while trying to figure out how that gray thing in the picture was a really big bacterium.

  4. I think there’s a middle of the road where both are very exciting concepts.

    Operator overloading IS a great way to clarify code. BUT only when there are rules in which those operators are “okay”.

    For example, overloading the + operator is okay as long as it acts like addition over its operands. Like adding two money objects. For this, some way of defining and verifying identity, associativity, commutativity would be helpful.

    For this reason, it looks like Haskell monads and Lisp macros are different facets of the same thing. With regards to the latter, it seems Lisp achieves this power, conceptually, using a particular kind of monad – the list monad parameterised with a union type of lists and atoms. That means you can flat map syntax in the same way Haskel monads allow you to flat map all kinds of impure computation (the programmable semi-colon).

    What would be interesting to see would be a language that combines these two ideas, which has both the syntactic flexibility of macros with the type-safe rigour of monads.

Leave a Reply

Your email address will not be published.