←back to thread

A list is a monad

(alexyorke.github.io)
153 points polygot | 3 comments | | HN request time: 0.635s | source
Show context
brooke2k ◴[] No.44445948[source]
As far as monad tutorials go, this one seems quite good. I like the categorization of monads between "containers" and "recipes".

However, I personally think that monad tutorials tend to give people the wrong impression and leave them more confused than they were before, because they focus on the wrong thing.

A monad is not a complex concept, at all. IMO a more useful way to present the topic would be with one separate lesson for every common monad instance. Start with Maybe, then IO, then maybe State and List, and so on... because ultimately, every instance of a Monad works very differently. That's why the pattern is so useful in the first place, because it applies to so many places. (Note: this is a criticism of monad tutorials in general, not this one in particular, which seems to do a decent job on this front).

In my experience, people new to Haskell focus way too much on getting the "a-ha" moment for monads in general, when really you want a bunch of separate "a-ha" moments as you realize how each instance of a monad takes advantage of the pattern differently.

I also tend to think that monads are best demonstrated in Haskell rather than in other languages, if only because the notation is so much less clunky. That may just be me though. (EDIT: well, also because almost no other languages have typeclasses, so you have to approximate it with interfaces/traits/etc)

Also FYI: in part 2, the code examples have extra newlines in between every line, which makes it hard to read (I'm on firefox, if that matters).

replies(15): >>44446327 #>>44446377 #>>44446564 #>>44446988 #>>44447713 #>>44448118 #>>44448413 #>>44449093 #>>44449627 #>>44449895 #>>44450873 #>>44450887 #>>44451012 #>>44451851 #>>44458827 #
aeonik ◴[] No.44446988[source]
I think you are right. I don't think I've fully mastered the concept yet, but what you are saying resonates with me.

I've been trying to grok monads for almost a decade. More and more I'm beginning to realize how "mundane" the concept is, and the usefulness really is just that specific pattern of mundanity.

Similar to pipelines on Linux, they are pretty basic, but their ubiquity and their use in composing unrelated things together is really, really useful, and you only get that if you use them in a variety of different ways.

Monads are extra cool because of the mathematical rigor behind them, and that's what I'm still trying to appreciate.

replies(2): >>44449406 #>>44451047 #
cynicalkane ◴[] No.44451047[source]
What helped me grok the mathematical rigor is: If you have a series of monad operations that exist purely in monad world -- in Haskell, if your expression is parametric over the type of the monad -- you shouldn't have to worry about how you do it.

This is what monads being categorically commutative ("a monoid in the category of endofunctors") buys you. You want to turn monad X into monad Y? Sure, just join, flatten, return, bind in whatever way makes the type checker happy. Anything that only uses what's in the Monad typeclass must necessarily be a monad morphism, so if you're generic over your monads, you get that for free. And of course `fmap` and `bind` are required to be parameterized monad morphisms, so there's a lot you can get for free.

replies(1): >>44451535 #
1. chongli ◴[] No.44451535[source]
I think you mean associative. Neither monads nor monoids are commutative.
replies(1): >>44456640 #
2. cynicalkane ◴[] No.44456640[source]
...Sorry, that was unclear. Monad-as-monoids being associative corresponds to certain categorical diagrams being commutative.

It's the concept of categorical commutativity that's what's useful. A collection of types and functions is "commutative" if every way to get from type A to type B yields the same result. It happens a lot in Haskell where most or all of the operations you're interested in commute with each other, which is how Haskell gets its reputation of "if it compiles it works". In particular, if you `fmap` or `bind` two commutative functions, the result becomes commutative, too.

replies(1): >>44468659 #
3. chongli ◴[] No.44468659[source]
Very misleading since monoids include a binary operator and the algebraic definition of commutative would imply that A * B = B * A. Clearly this is false if A and B are strings and * is concatenation (which forms a monoid with the empty string as identity).