"What actually is a monad, and why should I care?"
Various people had a go, or directed the OP to their favourite exposition. Not wanting to miss this opportunity to promote my Cyrus language, I also replied:
____
This is just a
practical approximation to give you a feel for how I see the whats and
whys of Monads. Happy to take corrections if I've actually got it all
completely wrong. And apologies to anyone who feels patronised by my
jolly style or who is a Haskell programmer and whose teeth start to
grate..
A Pure Functional World
Say you love functions sooo much that you want everything to be a function in your programs. So that's:
output=f(input, input, ..).
Everywhere. And for the same inputs, you always get the same outputs.
Programs are built by chaining functions:
final-output = f1( f2(3), f3(4,"banana") )
No State?!?
First thing this means is no state
- you can't have persistent state. State as-in "value that something
takes at some point" can only be represented by those input numbers and
strings: 3, 4, "banana", and the outputs of functions.
So you can have "state", as long as it keeps being juggled transiently between the inputs and outputs of functions, maybe recursively.
So you can have "state", as long as it keeps being juggled transiently between the inputs and outputs of functions, maybe recursively.
But you really want
state, because the Real World has absolutely bloody tons of it.
Computers and programs that do real work have user interfaces and
databases.
So
you're just going to have to juggle and maintain those transient values
between functions, and do some recursion to keep the plates spinning.
If only there were a way to make all this value juggling and plate spinning easier. A functional programming pattern of some sort.. it would have to have an academic, intimidating name, to put people off thinking that State is Great, or anything like that.
If only there were a way to make all this value juggling and plate spinning easier. A functional programming pattern of some sort.. it would have to have an academic, intimidating name, to put people off thinking that State is Great, or anything like that.
Enter The Monad...
In fact, all you need to do is to juggle bigger, smarter values!
A Monad is just an aggregate, a container, a wrapper, a raiser-upper of state which allows you to still be completely functional and yet still pass around all the state you need in your entire program.
Indeed, to make the point: you could go really nuts and have a program like this, for your database:
end-of-day-database-state = f5( f4( f3( f2( f1(start-of-day-database- state)))))
A Monad is just an aggregate, a container, a wrapper, a raiser-upper of state which allows you to still be completely functional and yet still pass around all the state you need in your entire program.
Indeed, to make the point: you could go really nuts and have a program like this, for your database:
end-of-day-database-state = f5( f4( f3( f2( f1(start-of-day-database-
where each fN() is a transaction, or a selector that carries forward the selections plus the entire database.
A better notation, perhaps for browser GUIs, would be:
A better notation, perhaps for browser GUIs, would be:
f1(starting-DOM-state).f2(). f3().f4().f5()
which can pass the DOM state through, along with, again, selections - a subset or working set. Look familiar?
which can pass the DOM state through, along with, again, selections - a subset or working set. Look familiar?
So, in general, you want to apply little functions to little bits inside the whole passed/juggled state. You never change the whole database or the whole GUI at once. Perhaps just a field in the database or GUI. You may have intermediate states that get added to the aggregate and passed on to the next stage.
Actually, f1()
in both examples is special, because it takes a "simple" state or value
and raises it up to this wrapper/aggregate/super-value - it creates a
Monad. It's like $() in JQuery. Similarly f5()
is special, at least in the database example, as it goes back again to
the simple state. The simple state doesn't know about all this
aggregate, compounding stuff: it doesn't have the functions or methods
that juggle and spin plates.
Why
not just have explicit, big state objects instead of Monads, and only
use pure functions to transition those objects between states?
Exactly. It would be way easier
than all this juggling and plate-spinning, and much easier to see what
was going on. You could give those state objects URLs, and everything.
:-)
Your notation in FP would be `f5 . f4 . f3 . f2 . f1`, or as a concatenative PL `f1 f2 f3 f4 f5`.
ReplyDeleteAnyhow, you seem to be focusing on the state monad use case. Monads are also useful in support of effects, backtracking models, dependency injection, and elsewhere.