def get_user(id):
# returns None if no such user exists
return Database.Users.get(id)
def send_message(user):
user.send(message)
def main():
user = get_user(1)
# uhoh -- this could be None and we didn't handle it!
send_message(user)
So, we add a None check: def main():
user = get_user(1)
if user != None:
send_message(user)
But... what if we want to log the status of that send_message call? def send_message(user):
try:
user.send(message)
return None
except Exception, e:
return "Failed to send message; {0}".format(e)
(Note that this is a contrived example, please don't critique the general dumbness ;)).Now...
def main()
user = get_user(1)
if user != None:
response = send_message(user)
if response != None:
log(response)
As you can see, it's getting a bit hairy. But, what if we had a class that dealt with the Nones for us? This is what a monad is: an interface, that many different instances implement, which provides some behavior. The following only deals with single-argument functions, but: def NoneMonad(Monad):
def __init__(self, arg):
self.arg = arg
def bind(self, func):
if arg != None:
next_arg = func(arg)
return NoneMonad(next_arg)
else:
return NoneMonad(None)
Now, we... def main(self):
NoneMonad(1).bind(get_user)
.bind(send_message)
.bind(log)
And, boom, the Nones are handled. Real, non-contrived Monads do more (and implement other behaviours -- like in dons' example, the Either response, or the Maybe monad, etc.), but hopefully this demonstrates the strength. Haskell's typically used as the example language, because there's syntax sugar in Haskell for making dealing with Monads prettier :).Having finally grokked them, it surprised me how simple the concept is. I think for people (like me!) coming from Java, Python, etc. who've not had to deal with the concept, there's this sort of imbued myth that they're a much more difficult concept than they really are. It's as simple as: a Monad is an interface, that can be implemented, that provides a construct for executing code in.
Please forgive any blinding mistakes I've made in my code.