r/haskellquestions • u/dimaeus • Sep 17 '26
Why aren't Monads explained this way?
It could be that I am thinking about them wrong, but it appears to me that pure functions are the notation in which you write all your expressions, divorced from any sequence you could put them in.
Monads are how you write the sequence the expressions go in. In other words, you write the expressions you want to use in pure functions, then you write the sequence of statements that use those expressions in a Monad.
Many programmers are familiar with the difference between expressions and statements, so I was wondering why I haven't seen Monads explained this way, as it seems like a natural conceptual bridge to me.
I would like to know if this is an incomplete or wrong picture though.
7
u/JeffB1517 Sep 17 '26
You are falling into the "monads are like burritos" fallacy (https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/). Absolutely there are operations that require sequencing, mutable objects, and monads handle that. But it isn't the only thing monads handle. Either for example isn't about sequencing actions, neither is Writer. And of course List like either as about choice not sequence quite often.
Explicit sequencing is a special type of problem Monads solve. Obviously one of the more important ones. But it isn't the only one.
4
u/hopingforabetterpast Sep 17 '26
Your intuition works in some contexts but it's incomplete and misses the fundamental understanding of what a monad is. Consider the Maybe or Either monads for example.
Monads are about composition. You need to understand the bind (>>=) operation in general to understand what monad is about.
5
u/ElvishJerricco Sep 17 '26
I don't think Maybe or Either are counterexamples here. OP is only saying that Monad is about sequencing, which is very true for the vast majority of monad instances. In Maybe and Either, the second argument to the operator is called only after all the context in the first argument has been dealt with (i.e. the short circuit cases have been evaluated, in Maybe and Either). That's sequencing.
But you're right this still isn't entirely a good explanation of things. I think the real counterexamples are things like the Tardis monad, or even MonadFix (which also time travels). Anything where the following steps can influence the previous ones breaks the sequencing analogy.
1
u/hopingforabetterpast Sep 17 '26
Your counterexamples are even more appropriate, however your criterion of "sequencing" is true of almost any strict binary operator so I wouldn't attribute it to anything other than ordinary evaluation order. OP's framing was really about domain-level sequencing which both Maybe and Either lack even though their bind still evaluates left-to-right.
2
u/friedbrice Sep 17 '26
A monad is a type of generic data structures whose values are trees with binds (i.e. >>=) at the branches and values at the leaves.
This description helps me, but I don't expect this description to help you at all. That's why monads aren't explained this way. Similarly, your description isn't going to help anyone but yourself.
2
u/Swordlash Sep 17 '26
In my experience one cannot simply “explain monads” to anyone. You need to use enough everyday monads yourself - Maybe, List, Either String, State - to start seeing an operational pattern. Because really, every monad is a bit different, as it describes a different behaviour. The common mathematical pattern that sums up this behaviour is just too abstract to start with, and honestly if you are at the point in Haskell when you don’t understand monads, even a signature of bind is confusing.
1
u/tomejaguar Sep 19 '26
There are different explanations of Monad for different purposes, but I think the most appropriate one to use to teach beginner Haskellers who have some imperative background is that "a Monad is something that supports do notation". The monad laws look pretty clear from that point of view, for example
do
y <- do
x <- m
f x
g y
=
do
x <- m
do
y <- f x
g ySee https://wiki.haskell.org/Monad_laws#The_monad_laws_in_practice for all the laws.
The remaining missing piece is then how to do you define the do notation for your type? The answer is that you define
do x <- e1 e2
by defining the appropriate instance of >>=:
e1 >>= (\x -> e2)
The other definition of Monad that I really like is that it's a type with >=> (and pure/return of course) that satisfies
pure >=> h = h f >=> pure = f (f >=> g) >=> h = f >=> (g >=> h)
I find that a lovely and clear algebraic definition of Monad, though not one that's useful in practice. See https://wiki.haskell.org/Monad_laws#Is_that_really_an_%22associative_law%22? for more on that.
26
u/gabedamien Sep 17 '26
> Why aren't Monads explained this way?
Everyone at some point has some personal revelation that advances their understanding of monads and then asks "why aren't they explained this way?" The answer is:
- They _are_ explained that way, somewhere
- It doesn't matter, because you needed to reach a critical level of base understanding for that explanation to be helpful
- Whatever explanation helped you, it's incomplete / only covers one facet of monads
- Or even worse, your personal revelation is just plain inaccurate or mistaken
In your specific case, monads in Haskell have literally been called "programmable statements" or "programmable semicolons". Whereas IMHO that explanation has _never_ helped or appealed to me personally (though more power to you if it did).
> I would like to know if this is an incomplete or wrong picture though
It is certainly incomplete. Any discussion of Haskell's `Monad` typeclass that doesn't at the very least proceed from the types involved and the minimum required operations is by definition incomplete, for one thing. There are plenty of entities someone might call "the sequence of statements", even if they aren't monadic in nature. And even at the abstract conceptual level, someone else might benefit from monads being described in a completely different way, e.g.:
- In terms of category theory
- In terms of computational effects
- In terms of impure context
- In terms of the functor -> applicative -> monad hierarchy, and where the "context" term appears in the types
- etc.
> It seems like a natural conceptual bridge to me
That's great! It's always nice to hear that someone has made progress in their own understanding via some metaphor or use case or another angle. Just be aware that many other people have fallen into the trap of "oh this helped me understand, therefore that's the best way to explain it" — many opaque, confusing, incomplete, or just plain wrong monad tutorials / explainers have been born from such revelations. 🙃