Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: What is a monad?
100 points by Azuldolphin on Dec 12, 2010 | hide | past | favorite | 43 comments
I'd like to start digging into functional programming beyond what is available in C# and Javascript, and began by reading a little about Haskell. There are a lot of mentions about something called Monads, which are part of category theory.

Can someone provide an explanation that would make sense to an experienced developer in the OOP world?



It's a design pattern for encapsulation, with similar goals to OO but different methods. Rather than telling you what a monad is, I'll just tell you the goal.

OO is designed to hide the dangerous parts of the world from you. The dangerous parts of the world (or at least some dangerous parts of the world) are encapsulated inside little black boxes with well defined interaction points. If you interact only through those little boxes, you should be safe. For instance, a logger object gives you 1 methods: writeLog (I'll ignore logging levels). The details of actually writing logs are not your business, and you (in principle) don't need to worry about them.

Monads are stricter. A monad puts you into a box and only gives you a few interaction points with the outside world. You can do whatever you want in a monad, but you are never allowed to leave the box. Inside the logger box, you are permitted only pure functions (functions with no side effects) and writeLog.

So basically, in an OO world, code using a logger might call os.unlink("/var/log/myprogram.log"). This would interact in a harmful way with your logging mechanisms. In a monadic world, from inside the logging monad, you are not given access to os.unlink.

Thus, f: a -> Loggable b in the monadic world (where Loggable b is an b living inside the box) is safer than f: (Logger, a) -> b in the OO world.


A monad puts you into a box and only gives you a few interaction points with the outside world. You can do whatever you want in a monad, but you are never allowed to leave the box.

This is not true for many commonly used monads, except for the IO monad. You can extract values from the list monad, Maybe monad, state monad, etc.

Put simply, a monad specifies how values can be wrapped in a 'box', and how such boxes are combined. For instance, Maybe is a box that can contains either a variable or nothing. In Haskell:

data Maybe a = Nothing | Just a

The Maybe monad specifies how expressions resulting in a Maybe are combined. Expressions are evaluated until/unless one of the expressions returns 'Nothing', and the value of the monad becomes Nothing.

Comparably, the IO monad specifies how IO actions are combined, the State monad combines expressions in such a manner to create 'state', etc.

We have tried to illustrate Monads with a Haskell-ish example here:

http://www.nlpwp.org/book/chap-words.xhtml#id3390030


So, a sort of sandbox function?


Yes.

But, more like sandbox type.


Hmm, I see. Does it also execute code, like a sort of exception handler, or is it just for limiting/allowing access to scope?


A monad is a type that has certain associated functions — to wrap values in the monad and do calculations on what's inside. The type itself obviously cannot execute code, but the associated functions obviously do. Monads can be used to implement exceptions.

As an example, lists are monads. The operator for doing calculations with the value in a monad is >>= (pronounced "bind"). To double every item in an array, you could do:

    [1, 2, 3] >>= \n -> [n * 2]
(The syntax "\n -> [n2]" defines a function that takes one argument, n, and returns a list containing n 2.)

There's clearly work going on behind the scenes to pass each value in the list to the associated function as "n", and then combine all the resulting [n * 2] lists into one big list of the same type as the original. But that's all transparent to the programmer. He only sees the interface that the monad offers.


Hmm, I see. The problem with my understanding it is that people are describing its properties and I have to build the mental model from them.

Are Python list comprehensions monads?


Well, it's the type itself that's a monad. So the question would be, are Python lists monads thanks to list comprehensions? And the answer is: Kind of. The idea of a monad in functional programming is that it's a generic type that can have a lot of different implementations.

The two operations that must be defined for a monad are:

• Return: You pass any value and it returns a monad encapsulating that value

• Bind: You pass a function taking an argument of the type wrapped by the monad and returning another value wrapped in the monad, and it returns a value of the monad

With these two operations, you can accomplish a surprising range of tasks. Python borrowed list comprehensions from Haskell, where they are based on monads — but in Python, they're kind of orphaned from their monadic roots.


This makes it much clearer, thanks. Those two operations weren't mentioned anywhere else that I saw, and they are very helpful in explaining what monads are.


Monads have nothing to do with OO. Ignore this guy's comment and read samstokes' instead.


What, no one is giving the standard answer of "a monad is a monoid in the category of endofunctors?"

A category is something like a set, but combining the objects with allowed operations. (How very OOP!) The available functions are first-class citizens (called arrows). The objects are the domains and ranges of the arrows, and their internal structures are not exposed. Arrow composition is associative when it is defined. (You can only compose an arrow if the range of one is the domain of the next.)

A functor is just a (natural) function on categories mapping both objects and arrows in a compatible way. Endofunctors map to the same category.

As each object in this category of endofunctors is a function we want to compose, we have to be given a way to do that. This is what that the monoid here does -- it's a way to describe the allowed ways of combining natural transformations, including any systematic tweaks to be done during the combination.

(The classical definition of a monoid is just a set with an associative binary operation with an identity.)


The paragraph starting "As each object in this category..." made no sense to me. I can explain the what a monoid in the category of endofunctors is, how it relates to a Haskell monad and maybe you can explain what you meant.

OK, a monoid in the category of endofunctors is an endofunctor F together with a natural transformation (the multiplication of the monoid) from F composed with F to F, and another natural transformation from id to F (called the unit). In Haskell F is the type constructor of the monad, the unit is called return and the multiplication is usually called join (and in the case of the list monad is also known as concat).

(Note that the definition of monoid needed here is not that of a set with associative binary operation, but the more general "monoid object in a monoidal category". Instead of a set S and a multiplication S x S->S, where x denotes cartesian product, we want a functor F and a multiplication F o F->F where o denotes composition. This is an instance of the general sort of monoid since the category of endofunctors is monoidal with respect to composition.)


I didn't want to give the full categorical definition in terms of what a monoidal category allows, because I don't think that adds much, but I suppose I flubbed making it simpler. I just wanted to make the point that the monoidal portion determines how the composition occurs -- a given type constructor can be a monad multiple ways.


and here I was ready to make a snarky comment about a monad being a specific instance of a polyad


Actually, this made a lot more sense to me. (I guess I really am a math major!)


DON'T start functional programming with monads. Familiarize with currying, pattern matching, how to create data types in Haskell, using recursion instead of loops, higher order functions, list comprehensions, type classes, polymorphism in Haskell (different than subtyping in OOP). Ignore monads for a while. To understand monads you must have a good grip of those concepts. You can start with http://learnyouahaskell.com/chapters.

You'll see Haskell tutorials delay telling about the concept. There's a reason.

For a bird's eye of monads you can check this: http://www.reddit.com/r/programming/comments/64th1/monads_in...

If you are ready, read and do exercises in http://blog.sigfpe.com/2007/04/trivial-monad.html and then http://blog.sigfpe.com/2006/08/you-could-have-invented-monad....


A cheap and unexciting trick for passing a value through a couple of functions. (Monads are cool, but it's important to understand that there's nothing, nuttin', whatsoever fancy about them, so I like to call them a "cheap trick".)

This is a good intro: http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/ba...

Be sure to mentally replace "monad" with "warm fuzzy thing" when reading it and it should make sense.


Actually, the effects of that trick are nothing less than exciting.

For example, that trick allows you to pass information from future (one of Wadler examples).


Let's say you wanted to implement I/O in a language without side effects. You could put all your interactions with the world in a special "World" object. Every time you called world.putString("foo"), you'd get back a new world object that represents the state of the world with "foo" having been written out.

So the code (quoting from samstoke's hello world):

    main :: IO ()
    main = do
      putStrLn "Please enter your name"
      name <- getLine
      putStrLn ("Hello " ++ name ++ "!")
would get translated to:

    main :: World -> World
    main world = let newWorld = putStrLn world "Please enter your name" in
                   let (newerWorld, name) = getLine newWorld in
                     let newestWorld = putStrLn newerWorld ("Hello " ++ name ++ "!") in
                       newestWorld
Note that this makes the order of operations explicit, and that no World needs to be modified. Note also that now main has to take and return one of these World objects, so that a World needs to be threaded through all computations that will interact with the World (just like IO actions can only be executed from within other IO actions).

A monad lets you thread implicit state through a computation.


Monads are red herrings, if what you're interested in is getting started with functional programming (or even Haskell specifically). It's an unfortunate flaw in the Haskell literature that makes it seem like you have to grok monads to learn Haskell; you don't.

Monads enable syntactic sugar. If you're getting started with Haskell, you'll notice that when you write code that does I/O, you use a weird imperative-looking syntax ("do notation") that looks different to the normal functional style:

    main :: IO ()
    main = do
      putStrLn "Please enter your name"
      name <- getLine
      putStrLn ("Hello " ++ name ++ "!")
'putStrLn "Hello"' doesn't actually print anything; it returns an IO value that, when interpreted by the Haskell runtime, prints something: that interpretation takes place when 'main' is run. The do notation is syntactic sugar for creating a sort of compound IO value that interprets as a bunch of actions rather than just one. The reason you can use do notation for IO but not for (all) other Haskell code is that IO values are monadic (which is another and possibly more useful way of saying "IO is a monad"): that just means that they behave in a certain way when combined (to produce that compound value) and obey certain laws to make the do notation well behaved.

Monads are a design pattern to abstract away repetitive functional code. For example, if you write a lot of pure-functional code you sometimes end up having to pass around a 'state' parameter. If a function reads or writes from the state, then any function that calls it has to pass in the state, and so on. This leads to a lot of functions with an extra state parameter, many of which don't even care about the state except to pass it down the call tree. An improvement would be to write a higher-order function which took a function which didn't care about state and wrapped it to produce one that just passed the state through. The State monad encapsulates this wrapping and lets you clean up the rest of your code.

Monads are what's between the lines of an imperative program. Bourne shell scripts have the default error-handling rule that they ignore failing commands unless it's the last one executed, or put another way, they run in a monad that ignores errors:

    cat nonexistent.txt   # prints an error message
    echo Done.            # still executes, prints "Done."
    # script returns success
But you can tell it to run instead in a monad which stops after the first error:

    set -e                # change the monad, i.e. the error-handling rule
    cat nonexistent.txt   # prints an error message
    echo Done.            # never runs
    # script returns failure
Old-school Visual Basic has the opposite default, but you can make it behave like a shell script with "ON ERROR RESUME NEXT". Yes, VB had monads.

Monads are a specific example of higher-kinded polymorphism, which is a very powerful and useful concept that's starting to enter the programming mainstream (examples are template concepts in C++ and LINQ in C# and .NET). Parametric polymorphism (List<String> in Java and C#, etc) means you don't have to write a 'reverse' function that works on lists of strings, and another 'reverse' function for lists of ints, etc; you can just write a generic reverse function that works on lists of any kind, because it doesn't need to know the details of the contained type, just how to iterate over a list. However, if you want to reverse an array, you still have to write a new 'reverse'. If your language supports higher-kinded polymorphism, you can write a generic reverse function that works on any kind of container, because all it needs to know is that the container has some well-behaved method of iteration.

(The LINQ example is a bit more subtle, because C# doesn't support higher-kinded polymorphism, but LINQ is a hard-coded exception to that rule. The cool LINQ syntax works for any type which provides certain operations and behaves in a certain way - which just happen to coincide with the requirements for the type to be monadic.)


Each of your statements seems plausible, even profound in itself.

Then I try to combine them and my head explodes.

You don't need to understand Monads to understand Haskell but they're how you print "Hello world"?? Yeah. Your other example also seem pithy and worthy, and again leave me feeling like the result is utterly opaque. You've shown goodness and power and all but it feels like you're holding the real definition behind your back to make the magic look even more magical-er.

How's-about-ya-spit-it-out. What the heck's a monad?

I feel like I've gotten as far as thinking that a monad's like a little interpreter/pre-interpreter. You pass it something like raw code and it binds more meaning to the variables as well as change the context of execution etc, all before that code gets eventually interpreted. Kind of like how you pass fragments of code to Ruby functions and kind of like how c++ templates are parameterized by type.

Wikipedia says "A monad is a construction that, given an underlying type system, embeds a corresponding type system (called the monadic type system) into it (that is, each monadic type acts as the underlying type). This monadic type system preserves all significant aspects of the underlying type system, while adding features particular to the monad." http://en.wikipedia.org/wiki/Monad_(functional_programming) At least that definition doesn't leave me feeling like someone's said "I can't tell you but they're really great"...


No, actually, i've read dozens of explanations, i went metalinguistic and read discussions about discussions of monads, and this guy is totally correct, the ONE SINGLE most important thing to know about a monad, it would seem, is that you are not required to know what a monad is to use it.


You're right - I didn't explain what a monad is a priori, just some of their properties and reasons they're useful. Thanks for calling me out on that, as I should have made it more explicit.

I didn't mean to "hold the real definition behind my back", just felt that others in this thread had explained the definition better than I could. I also wanted to make the point that the definition is not that important unless you actually want to implement your own monad.

You don't need to understand Monads to understand Haskell but they're how you print "Hello world"??

Yes, there's no contradiction here. The idiomatic and easiest way to write Hello World in Haskell involves some unusual, but fairly intuitive, imperative-looking syntax. That syntax only works because the Haskell IO API is monadic, but you really don't need to know that, nor to understand what a monad is, in order to print Hello World.

LINQ is very similar to Haskell's do-notation, and LINQ providers (LINQ-to-Objects, LINQ-to-SQL etc) are monadic, but you don't need to know what a monad is to write "from u in users where u.age > 21 select u.name". If you want to write your own LINQ provider, though, it's probably worth knowing the monad laws.


For a more thorough, probably better written although longer explanation, I say going to http://blog.sigfpe.com/2006/08/you-could-have-invented-monad... and reading through that, but I'll give it my own, shorter go and see if you can follow.

Monads are basically a design pattern dealing with special data types. Let's say you're in some situation where there's nondeterminism—each function doesn't return just a value, but several possible values. To use a pseudo-C++-like type system, all of your functions have a signature like

    List<B> doSomething(A);
where it returns a list of B's to represent every possible value. You want to chain these together, and the naïve way is

    foo = doSomething(x)
    bar = []
    for someFoo in foo:
        bar += doSomethingElse(someFoo);
    baz = []
    for someBar in bar:
        baz += doSomeOtherThing(someBar)
So for every function, you have to repeatedly accumulate the possible values for every possible value so far. If you have higher-order functions, you can encapsulate this in a function like this

    def bind(f, list):
        results = []
        for value in list:
            results += f(value)
        return results
which means the above example could be rewritten as

    bind(doSomeOtherThing,
         bind(doSomethingElse,
              bind(doSomething, [x])))
Now, the type of bind looks something like

    List<B> bind(List<B> f(A), List<A>)
which is to say it takes a function from a normal type to a "special" type—in this case a list—and applies it to a "special" type—in this case, every element of a list. In this case, we'd say that List, together with the bind function, is monadic. The Haskell types look more like

    bind :: (a -> m b) -> m a -> m b
    -- or for our particular example
    bind :: (a -> [b]) -> [a] -> [b]
The key here—and it's a simple example, so it's probably hard to see how it extends to the hype given—is that you've got a "special" kind of data and you're taking functions which operate on normal (non-special, in this case, non-list) data and writing functions to use them on special data with little work. The cool thing is that it's a really common pattern, which is why Haskell programmers mention it a lot.

(Note: in Haskell, 'bind' is actually an operator written >>=, and the order of its arguments are reversed, so its type is

    >>= :: (Monad m) => m a -> (a -> m b) -> m b
but there are reasons for writing it the way I did.)


One of the clearest explanations I've read. Thanks!


Upvoted for excellent explanation. Thanks.


Lovely, thank you.


Monads are (quote) elephants: http://james-iry.blogspot.com/2007/10/monads-are-elephants-p...

Monads can be implemented in OO languages, like ruby: http://moonbase.rydia.net/mental/writings/programming/monads...

Tony Morris, on of the authors scalaz (which implements monads, among other things, in scala ): http://projects.tmorris.net/public/what-does-monad-mean/arti...

A one that was considered a very good explanation on the topic: http://blog.sigfpe.com/2006/08/you-could-have-invented-monad...


My friend told me recently that he invented monads in Javascript:

  result = monadicObj
         .action1(arg)
         .action2(arg2);
I told him that he needs variable binding operations for fully fledged monads:

  result = monadicObj
         . x <- action(arg)
         . y <- action2(x,arg2)
         . action3(x,y,arg3)
         . return (x+y);
Otherwise, his invention is much more like Applicative, because we cannot pass values between actions.

So here it is: monads are just objects with overloaded and extended "." operator and with special function "return" that modifies object (in accordance with object meaning) and returns it's input value unchanged. That new operator allows us to bind return results if we want so. Overloading of "." allows us to implement various interesting operations - passing state, executing optional computations, executing non-deterministic computations, probabilistic computations, etc.

You incapsulate the meaning of computation inside object, so you can pass it to some evaluator without that evaluator knowing that you pass him non-deterministic computation instead of monte-carlo monad or vice-versa.



Moggi used monads in category theory to define computations with side effects in functional programming. The basic insight is that in addition to the values of various types in functional programming, there are "computations" of various types. Examples of "computations" would be exceptions or continuations. Each monad defines for each value type a computation "containing" that type, and the whole type system of values you started with can be embedded in a new type system with new computation types.

Monads in category theory are an algebraic device for embedding a category--usually a cartesian closed category--of types of values into a new category with types of computations. However, the correspondence between Haskell monads and category monads are related by a series of adjunctions.

Suppose that C is a cartesian closed category and M:C->C is a monad with natural transformations e:1->M (the unit) and u:MM->M (the multiplication).

We assume a fixed choice of products and compatible exponentials: for each type A of C,

  A x ( ) -| [A -> ( )]
Here's the adjunction

  MA -> [[A->MB] -> MB]
  ---------------------
  MA x [A -> MB] -> MB
  ---------------------
  [MA -> MB] x MA -> MB
  -----------------------
  [A -> MB] -> [MA -> MB]
The final map is given by currying, but it can also be motivated as follows if you think of the exponentials as internal hom sets. If g:A -> MB is in C, so that g:A->B is in the Kleisli category C^M, then u_{MB}oM(g):MA->MB. We can write this as the lambda term \lambda x\in A A -> MB.u_{MB} oM x

This lambda term corresponds to composition in the Kleisli category C^M of C, and belongs to the internal language LL(C), the simply typed lambda calculus determined by C. Under the Curry-Howard-Lambek correspondence, the lambda term corresponds to the required map of C.


It's the operator that allows to chain two statements together. It's written ";" in Pascal, and is often implicit in other languages.

When a language explicitly talks about monads, it's because it lets you overload that operator, i.e. it let's you give alternative definitions of what it means to chain statements together.



Unfortunately "monad" gets used in a few contexts unrelated to the sense the OP is asking about. Similarly, the (cancelled) TV series Caprica recently started using "monad" to mean "monotheist".


On the other hand, it seems that if one is willing to propose a similarity between one of the cornerstones of rationalism and the misuse of "monad" by a fictional character on a canceled television series, one might be more open to seeing more direct lines of intellectual descent from an inventor of the calculus to functional programming.

The embedded type system of a programmatic monad remains unchanged despite the monad's combination into higher level structures - a somewhat Leibnizian characteristic.


Slides from functional programming class might clarify things a bit [PDF].

http://www.it.uu.se/edu/course/homepage/avfunpro/ht10/notes/...


I wrote some stuff about monads on HN a while ago that some people found helpful: http://news.ycombinator.com/item?id=247446


There are already a number of excellent answers, but I'll try my hand. You don't know something until you can explain it 3 different ways.

Haskell excels as a functional language because it has excellent piping, Monads are just another form of piping with particularly great syntactic and psychological properties. They act as wrappers around a direct type and setting the return type of a function as a monadic type (such as IO () or [Int] or Maybe Bool) means that the primary type is () or Int or Bool, but there's something special being passed along as well.

In practice this saves typing since you don't explicitly pass the special monadically-hidden information. It also psychologically lets you think of simple types being wrapped in contexts which have certain properties. Some contexts can be unwrapped, some cannot. Some contexts can transform into other contexts directly, some cannot. Learning the behavior of each monad independently teaches you about these behaviors and then becomes important in advanced Haskell programming.

When learning, avoid them. Learn how to use IO by rote and ask in IRC about the confusing type errors that will arise. They usually translate as "you tried to combine two pipes which don't fit, so that monadic special sauce was lost". Part of learning Haskell is learning all of the joints and adaptors which help you to combine types effectively (including monads).

When you have a firm grasp of using compositions and maps and filters, start with the Maybe monad. Implement it and use all the general monad adaptors on them. Then learn the basic State monad because it makes the special sauce very explicit. Learn IO last because it's really a special case and should never be introduced as a monad.


I'll have my stab at making a short explanation without code or lots of technical stuff. So here's some handwaving that may contain mistakes:

Monads are sequential processes, which are combined to make bigger processes. getLine is a monad, so is putStrLn "hello". You can combine two monads into a bigger monad using the >>= operator, which would be the "means of combination" which is extensively discussed in the Structure and Interpretation of Computer Programs lectures. Simplest monad program I can think of is echo = getLine >>= putStrLn.

I learned monads by doing simple stuff like guess the number and hangman, first writing them in the do-notation (syntactic sugar for a mini-imperative language) and then converting that to concrete notation using >>=.

Monads are not only useful for IO, but also other sequential processes such as parsing, pretty printing, binary file io and stateful inside but functional outside algorithms (ST monad).

Disclaimer: this was written by a Haskell newb, recently introduced to the wonderful world of Monads.


From my limited understanding garnered by listening to SE Radio, monads are basically a way for Haskell programs to execute actions (rather than simply computing values), so that your program can ultimately DO something like write to a file. As you probably know, the functions aren't supposed to contain any side effects: you don't want something unexpected to happen when you just want to calculate a value. It would be like a spreadsheet that printed out a page every time you entered a certain cell - might make sense in a one-off situation but in the long run it's just inviting trouble.

So monads allow sequences of actual actions to be packaged together and given preconditions and then executed in a safe manner (perhaps with an eye to concurrency). You get to maintain the exquisite purity of functional programming while still writing software that, you know, gets stuff done occassionally.

If you were looking for an explanation of the mathematical concept though, sorry, ain't got a scooby.


The Wikipedia has a very good treatment: http://en.wikipedia.org/wiki/Monad_(functional_programming)

The monad is the axioms outlined in the article. The applicability of the monad are the logical consequences of its axioms, but it is no more than its axioms.

Happy hacking!


The short answer is to read chapter 14, probably more than once, before it makes sense. It took me 2 times: http://book.realworldhaskell.org/read/


Monads are a means of guaranteeing program sequentiality and maintaining state.




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

Search: