HN2new | past | comments | ask | show | jobs | submitlogin

> You don't need a monad abstraction to have things with monadic properties, and indeed often reality isn't quite perfectly shaped to theory, so forcing your object to fit the abstraction can be costly.

Please note that I was trying to explain what a monad is, to somebody who wanted to understand. I also suggested that people writing typical code shouldn't actually need to know this in order to do their jobs:

> Should you need to know this in most production code? Probably not! But if you're trying to implement something fancy that "works a bit like promises, or a bit like Python comprehensions, or maybe a bit like Rust error handling", then "weird containers with flatMap" is a very powerful starting point.

Monads are an incredibly stripped-down mathematical structure ("container-like things that support flatMap"). And as such, people who design certain types of programming languages or libraries may benefit from being aware of monads. At least for languages with closures. Surprisingly few languages can actually support monads as a first-class abstraction in the language, because to make first-class monads nice you need a certain kind of type system. Which often isn't worth it.

Where I probably differ from your opinion is that I think implementing "almost monads" like JavaScript promises is very often a mistake. The few places where JavaScript promises break the monad laws are almost all nasty edge cases and obscure traps for the unwary. Similarly, if you implement list comprehensions that break the monad laws, most likely you just get awful list comprehensions.

There are exceptions. Rust has a lot a "almost monads", but this is mostly because Rust function types are a mess thanks to the zoo of Fn, FnOnce and FnMut. Rust would be a simpler and easier-to-learn language if Future<...> actually followed the monad laws. But in this case, it sadly wasn't possible, and I would argue that Rust is worse for having so many "almost monads."

This may all make more sense if you knew my tastes in programming languages, which is "languages where all the parts fit together cleanly with no surprising edge cases that prevent 'obvious' things from working." One way you can accomplish this is to have some kind of simple mathematical structure underlying your language, and to avoid adding dozens of features that almost follow clean rules. C++ never took this approach, and so C++ library designers need to be aware of all sorts of interactions between weird corner cases.

So another way of summarizing my argument is "If you have list comprehensions that somehow don't follow the monad laws, then you're going to confuse users and permanently add technical debt to your language. Make sure it's actually worth it."



The Rust example is illustrative, and indeed I was thinking about it when I wrote my post. One valid angle is to say that languages should hide the reality of the machine from the user any time it would get in the way of the pure semantic description. Another angle though is to say that actually these concerns are important, and if the result is that the idealised abstractions aren't sufficient to capture them, then it's correct to put away the abstraction. It's not like ‘simple and easy to learn’ is a function of this elegance either; Haskell is hard to learn and Go is easy, so clearly there's something else to it.

You also mention list comprehensions forming a monad. I think this is also a good illustration of the difference. In Haskell the structure of a type tells you the dependency tree of a computation, so it's not a problem that Monad maps the type to itself. Your list monad is just a bunch of thunks pointing to each other either way. In imperative languages, types describe what has been reified and how it's organised in memory. In these, a list monad is an actively bad abstraction; you almost always want to distinguish the stateful computational pipeline (eg. an iterator) from the source and target storage (eg. an array). Neither of those are monadic for good reason.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: