Hacker News new | past | comments | ask | show | jobs | submit login

Wikipedia goes a long way, you know? You could do a lot worse than get it from there: http://en.wikipedia.org/wiki/Monad_%28functional_programming...

The term monad comes straight from Category Theory, a branch of mathematics. There are some rules, and anything that obeys those rules is a monad.

From the point of view of programming languages, any set of values/objects for which a particular set of functions exists is a monad. See wikipedia for what they are, exactly.

Monads exist on both dynamic and statically typed languages, but it is more difficult to explain them on dynamic languages, where you don't have types to explain the properties.

So many things can be monads. For example, collections can easily be monads, for it is easy to define "join" and "fmap" for them (one of the two possible ways of defining a monad):

* "join", aka "flatten", means that if we have a collection of a collection (a list of lists of x, a set of sets of y, etc), we can "flatten" it one level (that is, get a list of x or set of y);

* "fmap" means that, if we have a function that changes the objects inside that collection, we can create a function that changes the collection so that the objects inside it are modified. For example, if we have a function from strings to numbers, we can create a function that converts a list of strings into a list of numbers.

A list comprehension in Python is an example of these rules put in practice, though when using "if" you are going beyond these rules.

There are other monads besides collection and the usefulness of monads is that they work like an interface or API that is shared by all monads.

Going to Python again, consider the syntax:

  listC = [f(x, y) for x in listA for y in listB]
The function f doesn't care that x and y came from listA and listB, and if Python supported any kind of monad, then you could write something like this:

  monadC = [f(x, y) for x in monadA for y in monadB]
And that would work for any monad you passed. You would have abstracted away that you had lists, making your code more generic and, therefore, more reusable and less repetitive.

To go with an example you use elsewhere, you have a monad containing a file descriptor, a read line function and a convert string to number function, then you'd get back a monad of a number:

  monadN = [int(readline(fd)) for fd in monadFD]
Note that monads don't define a way to extract that number from inside them, but that really isn't necessary, as you can continue to apply functions:

  monadVoid = [print(n) for n in monadN]
If your original monad was a list of file descriptors, you'd print a list of numbers, one for each file. A Maybe monad (aka Option monad) would either contain a file descriptor or not, and you'd either print a number or not accordingly.

Another type of monad, the Future monad (also known as Promise), executes the function they are given asynchronously. So the monad containing the file descriptor was a future monad, then the code above would be executed and finish, but the number could be printed well afterward. I'll come back to this example at the end.

The usefulness or particular monads depends on the context, but the ones I'm familiar with mostly help avoiding side effects in functional programming. If you don't avoid side effects, you have no use for them. If you do, you'll inevitably come up with something equivalent to monads like the IO or State.

And the usefulness of the fact that they are monads comes from the fact that you can abstract away the specific type of monad they are, and work generically.

So, coming back to our number-printing program, let's say we are using a Future monad so that the number gets printed asynchronously, and we wish to test the program. If we use the Future monad, we'll probably have to sleep for a while and then see if the number was printed or not -- a test that may fail if the program takes too long to execute (say, the file is on a remote computer and has to be downloaded first).

One alternative is that we replace the Future monad with the Identity monad. The identity monad just holds a value, so any operation on it is executed synchronously. We can test our program using the Identity monad, so we do not have to way, and run it in production using the Future monad, so our program runs asynchronously.

We can do that because they are both just monads.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: