Most active commenters
  • kevinventullo(4)

←back to thread

A list is a monad

(alexyorke.github.io)
153 points polygot | 18 comments | | HN request time: 1.269s | source | bottom
1. kevinventullo ◴[] No.44450020[source]
So I come at this from a math background but I’ve always found these explanations to be overly complex. In the parlance of C++, I think of a monad as a template class T with the following properties:

1. For any class X, there is a canonical method

  F: X -> T<X>
2. For any class X, there is a canonical method

  G: T<T<X>> -> T<X>.
3. For classes X and Y, and any method

  f: X -> Y, 
there is a corresponding method

  “T<f>”: T<X> -> T<Y>.

—————-

Here “any type” means any type that is compatible with the template.

And then there’s some additional rules which make all these methods compatible, based on the different ways of stacking nested T’s and the “canonical” maps you get. Admittedly there is some confusing accounting here, but I also think most natural ways of constructing the above three requirements are going to satisfy them anyway. For List and Maybe it’s fairly obvious what the above methods are.

I dunno, maybe I have it wrong and someone can correct my understanding.

replies(4): >>44450173 #>>44450198 #>>44453789 #>>44457984 #
2. 4ad ◴[] No.44450173[source]
So you think that a monad which is an object with a simple definition in category theory is better explained in terms of C++?

I would agree that most of these articles about monads are bad. Just study the definition, then study what you can do with monads, it's not that hard.

replies(2): >>44450531 #>>44451357 #
3. Kranar ◴[] No.44450198[source]
This is like explaining chess by simply stating the rules. Like sure explaining the rules of chess is important but only knowing the rules provides for nothing more than a superficial understanding of a topic.
replies(2): >>44450545 #>>44451158 #
4. kevinventullo ◴[] No.44450531[source]
For people who are more familiar with C++ than category theory, yes.
5. kevinventullo ◴[] No.44450545[source]
I mean if someone is learning chess for the first time, then yes you should start with the rules rather than jumping right into waxing philosophic about positional strategy to show off how smart you are.
replies(2): >>44450885 #>>44451464 #
6. flebron ◴[] No.44450885{3}[source]
I think the point is that a monad is a useful concept _purely_ because of what it _allows_ you to do, and _not_ because of anything syntactical. Those rules that you're obviating there, the commutative squares, are precisely what then lets us have powerful intuitions about these objects. The type signatures matter a lot less. If, for example, you don't have functoriality (which is false for `std::vector`, for instance, since `std::vector<bool>` is special-cased) you lose the ability to reason powerfully about abstract algorithms.

Thus, explaining the syntax and where the type variables go is explaining the least relevant thing about monads to their power and importance. It's certainly easy to showcase both the syntax and the list and maybe monads, that's part of the "monad tutorial fallacy". Gaining intuition for how to think about monads _in general_ is a lot harder and requires practice. Like, yes, list and maybe are "containers", but is `(->) t` a container? Is `IO`? How do these compose, if at all? What is this about "effect" semantics, "I thought monads were just burritos/containers"? etc. These are the hard, both conceptually and pedagogically, questions. Yes you need to know the syntax to use it in any given programming language, but knowing what scabbard your knife fits in doesn't give you the skills of how to use knife :)

7. monkeyelite ◴[] No.44451158[source]
Yes, this is how you learn math. It helps to pair definitions with examples and exercises.
8. recursive ◴[] No.44451357[source]
Yes.

If you don't already know category theory, learning it is hard. The terms on wikipedia seem to form a dense graph of links. It's hard to get a foothold of comprehension. For people that already know C++, or are at least familiar with this syntax, this is more useful than describing it in haskell syntax or category theory. There seems to be a chicken and egg problem regarding haskell and monads. Learning c++ may be harder or easier than category theory. I'm no sure, as I don't understand either one of them. But this syntax makes more sense to me than something expressed in terms of category theory vocabulary.

replies(1): >>44454125 #
9. Kranar ◴[] No.44451464{3}[source]
Yeah I am aware that most teachers, like another commenter said, do teach math just by spitting out the rules and then people memorize them and sure who am I to argue against that. It's not how I learned math and most people I know who are well versed in math including those with PhDs (and working as a quant I am fortunate enough to work with many) also don't really learn things that way either...

When I taught my daughter chess at the age of 5, I did not teach her by laying out the rules and in general when I teach people anything, I don't start by emphasizing rules. Rules are often the least interesting part of any subject and I find rules are much easier to learn once a sufficient amount of motivation has been given first, and then we get to a point where we use rules to crystalize our intuition and express rigorously what we've come to learn. The rules are the end result of learning, not the starting point.

With chess, I taught my daughter by simply playing a simple game where I had a queen, and she had one king and two pawns, and her goal was to get one pawn across the board and my goal was to stop her.

The king and pawns are arranged so that with perfect play she is guaranteed a win, and eventually she learned the pattern that allows her to always win. I then switched it up so she gets the queen and I get the king/pawns but I arrange the king/pawns so that I will always lose if she plays perfectly.

After this, I added more pawns for white and a bishop for black. The motivation for adding these pieces is that to play perfectly and always win as white, you need to learn how pawns define the physical structure of the board, making walls and allowing for control over certain parts of the board, but this also comes at the cost of introducing clutter and making it hard for the king to maneuver.

After these principles are learned, then I introduce the knight, because the knight can jump over walls and isn't as burdened by clutter. I don't just put a knight in the game out of nowhere and make her memorize how it moves... by the time the knight is introduced, it feels natural to want a piece that has better maneuverability over the extra pawns.

And so on so forth... each piece is introduced with some kind of motivation for why it exists. It's not just there for the sake of existing because of some rule that you just need to memorize. It exists because it adds some kind of flavor and richness to the game and you end up absorbing the rules rather than just memorizing them.

Now I'm dwelling a bit on chess here... but the principle applies to programming as well. I don't think if you ever just listed the rules you did as a means of teaching someone about monads anyone would ever come to appreciate why these rules matter or why they should waste any time learning them and in fact I am fairly confident that this kind approach to teaching people functional programming is why it's taken so long for mainstream languages to appreciate these features and adopt them.

replies(1): >>44454082 #
10. gpderetta ◴[] No.44453789[source]
A monad would not be a template class in C++, it would a concept (more or less the c++ equivalent of an Haskell type class).
replies(1): >>44453911 #
11. feelamee ◴[] No.44453911[source]
monad like an idea - yes, it will be a concept. But a concrete monad - like list or maybe - will be a template class. Probably comment author means this
replies(1): >>44454415 #
12. feelamee ◴[] No.44454082{4}[source]
it's great you should write an article about this!
13. 4ad ◴[] No.44454125{3}[source]
Learning category theory to the level of understanding monads should take half an hour at most, and would constitute real understanding of what a monad is, versus this C++ explanation which is handwavy even in terms of C++. C++ can't even encode monads accurately!

But one doesn't even need to learn category theory. I assume that everybody has learned abstract algebra in high school, monoid, rings, groups, vector spaces and all that. A monad is just another kind of a structure like that. If you have studied abstract algebra in school then it should take 5 seconds to read the definition of a monad, a minute to understand it, and perhaps 10 minutes to see how various things such as errors or lists form monads.

Learning category theory, or indeed any sort of math from Wikipedia is an absolute futile endeavour.

replies(2): >>44455412 #>>44455515 #
14. gpderetta ◴[] No.44454415{3}[source]
Good point. In the same way we say that a pointer is an iterator or a vector is a container, when more precisely we should say that they model the iterator concept and container concept respectively.
15. housecarpenter ◴[] No.44455412{4}[source]
At least in my country (the UK), people generally do not learn abstract algebra in high school. That's a university-level topic.

I think there is a definite "step up" in complexity between the structures of abstract algebra such as monoids, rings, groups and vector spaces, and monads. All of those algebraic structures are basically just sets equipped with operations satisfying some equations. Monads are endofunctors equipped with natural transformations satisfying some equations. "Endofunctor" and "natural transformation" are considerably more advanced and abstract concepts than "set" and "operation", and they are concepts that belong to category theory (so I don't see how you can read and understand the definition of a monad without that basic level of category theory).

Your time estimates also seem wildly optimistic. A common rule of thumb is that reading a maths textbook at your level takes around an hour per page. I think the definition of a monad can be compared to one page of a textbook. So I'd say it'll take on the order of hours to read and understand the definition of a monad, and that's assuming you're already entirely comfortable with the pre-requisite concepts (natural transformations, etc.)

16. recursive ◴[] No.44455515{4}[source]
I learned none of those in high school or university. I did indeed fail for much more than 30 minutes to learn any of them from Wikipedia and other sources.

Over the years I've spent many hours trying to make any sense of monads with varying degrees of success. But mostly not.

Your assertions do not seem consistent with reality as I've observed it.

17. tel ◴[] No.44457984[source]
Yeah, that's correct. You also often see it as having that for any method `X -> T<Y>` there's a corresponding method `T<X> -> T<Y>`. Or you can have that for any two arrows `X -> T<Y>` and `Y -> T<Z>` there's a composed arrow `X -> T<Z>`. All are equivalent.
replies(1): >>44459832 #
18. kevinventullo ◴[] No.44459832[source]
Thanks for confirming; I wasn’t 100% sure what I wrote was equivalent to the `X -> T<Y>` definition, but I could see how you’d get one from the other using the unit/counit.