Skip to content

Comment on Monads, or Programmable Semicolons (2014)parent

Comments

Talking specifically about strict evaluation:

Monads rose to prominence in Haskell in order to deal with some specific technical challenges that stemmed from the project's decision not to make any compromises about lazy evaluation. Using monads for specifically that purpose in a language with strict evaluation would be a case of cargo culting Haskell.

That is certainly not the only use for monads. Haskell uses them as a general-purpose solution for things that other languages typically handle with an absolute zoo of special-purpose features. In that respect, you could argue that monads are, at least in the abstract, better than all those features, because they're one thing that can do the work of many.

However, if you're working in a language that already has some mix of strict evaluation, mutable variables, async/await keywords, exceptions, elvis operators, null punning, etc., introducing monads to solve those problems runs the real risk of running afoul of the xkcd.com/927 problem. Especially if those existing language have a tendency to not understand and respect the fact that they're now being used in code that's supposed to be observing the monad laws. Even implementing `Maybe` in a language with nulls can be surprisingly tricky to get right.

Which is where I stop having much interest in holy wars about this stuff. If you're lucky enough to be working in Haskell or a language inspired by it, that's awesome, you've got a whole menagerie of category theoretic abstractions to work with, and a language that's actually designed to help you use them with confidence. If you're not, then I'd argue that their use needs to be justified in much more specific, pragmatic terms, including an eyes-wide-open perspective on what the ergonomics and technical challenges are going to be like. Because, believe me, it's no fun having to work with a Try monad that can both return and throw errors.

Monads rose to prominence in Haskell in order to deal with some specific technical challenges that stemmed from the project's decision not to make any compromises about lazy evaluation.

Disagree. To an outsider, IO is the most prominent monad because it's very visible in small example programs (and something that separates the Haskell versions of those small example programs from those in other languages). But to a practitioner it's not a particularly important or interesting example, most use of the monad abstraction is not about IO, and I would certainly hope that the language (in the broad sense) would have adopted it with or without IO.

Using monads for specifically that purpose in a language with strict evaluation would be a case of cargo culting Haskell.

Disagree; even in languages which define an evaluation order, it's still very much implicit to a human reader. Being able to distinguish between accidental ordering and intentional ordering is really helpful to enable fearless refactoring. Like I said, post-Haskell languages like Idris often use strict evaluation but still see value in managing IO explicitly.

However, if you're working in a language that already has some mix of strict evaluation, mutable variables, async/await keywords, exceptions, elvis operators, null punning, etc., introducing monads to solve those problems runs the real risk of running afoul of the xkcd.com/927 problem.

The special-case syntax is often more suitable to the special cases it was designed for (it would be pretty tragic if it weren't). But the general-case syntax is necessary for general-case code. It can work pretty nicely as long as there's a direct transformation between one and the other; compare e.g. different ways of iterating through a collection, where you'll generally have a fully general function/syntax but also sugar that's more appropriate to restricted special cases.

Especially if those existing language have a tendency to not understand and respect the fact that they're now being used in code that's supposed to be observing the monad laws.

I'd argue that if your special-case solution doesn't conform to the monad laws then you already have a problem, even if you don't realise it yet. E.g. the fact that in many languages code that uses a map will break if that map contains null values, and the fact that implementing a valid maybe monad on top of null is difficult-to-impossible, are both reflections of the same underlying problem.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.