I just do not get what problem they solve.
closed as too broad by gnat, MichaelT, Bart van Ingen Schenau, Martijn Pieters, amon Feb 19 at 16:20
There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.
Monads are neither good nor bad. They just are. They're tools that are used to solve problems like many other constructs of programming languages. One very important application of them is to make life easier for programmers working in a purely functional language. But they are useful in non-functional languages; it's just that that people rarely realize they're using a Monad.
What is a Monad? The best way to think of a Monad is as a design pattern. In the case of I/O, you could probably think of it as being little more than a glorified pipeline where the global state is what is getting passed between the stages.
For instance, let's take the code you're writing:
There's a lot more going on here than meets the eye. For instance, you'll notice that
Think about it this way: let's pretend (for simplicity's sake) that stdout and stdin are the only files we can read and write to. In an imperative language, this is no problem. But in a functional language, you can't mutate global state. A function is simply something that takes a value (or values) and returns a value (or values). One way around this is to use the global state as the value that's getting passed into and out of each function. So you could translate the first line of code into something like this :
...and the compiler would know to print anything that's added to the second element of
So why do you care? Well, the advantages of functional programming over imperative program have been debated to death in several places, so I'm not going to answer that question in general (but see this paper if you want to hear the case for functional programming). For this specific case though, it might help if you understood what Haskell is trying to accomplish.
A lot of programmers feel that Haskell tries to prevent them from writing imperative code or using side effects. That isn't quite true. Think about it this way: an imperative language is one that allows side effects by default, but allows you to write functional code if you really want to (and are willing to deal with some of the contortions that would require). Haskell is purely functional by default, but allows you to write imperative code if you really want to (which you do if your program is to be useful). The point isn't to make it difficult to write code that has side effects. It's to make sure you're explicit about having side effects (with the type system enforcing this).
I'll bite!!! Monads by themselves aren't really a raison d'etre for Haskell (early versions of Haskell didn't even have them).
Your question is a bit like saying "C++ when I look at the syntax, I get so bored. But templates are a highly advertised feature of C++ so I looked at an implementation in some other language".
The evolution of a Haskell programmer is a joke, it's not meant to be taken seriously.
A Monad for the purpose of a program in Haskell is an instance of the type class Monad, that is to say, it's a type that happens to support a certain small set of operations. Haskell has special support for types that implement the Monad type class, specifically syntactical support. Practically what this results in is what has been referred to as a "programmable semi-colon". When you combine this functionality with some of Haskell's other features (first-class functions, laziness by default) what you get is the capability to implement certain things as libraries that have traditionally been considered language features. You can for instance, implement an exception mechanism. You can implement support for continuations and coroutines as a library. Haskell, the language has no support for mutable variables: using this combination of features you can implement them, again as a library.
You ask about "Maybe / Identity / Safe Division monads ???". The Maybe monad is an example of how you might implement (very simple, only one exception) exception handling as a library.
You're right, writing messages and reading user input isn't very unique. IO is a lousy example of "monads as a feature".
But to iterate, one "feature" by itself (e.g. Monads) in isolation from the rest of the language doesn't necessarily immediately appear useful (a great new feature of C++0x is rvalue references, doesn't mean you can take them out of the context C++ because it's syntax bores you and necessarily see the utility). A programming language is not something you get by throwing a bunch of features in a bucket.
Programmers all write programs, but the similarities end there. I think programmers differ far more than most programmers can imagine. Take any long-standing "battle", like static variable typing vs runtime-only types, scripting vs compiled, C-style vs object-oriented. You will find it impossible to rationally argue that one camp is inferior, because some of them churn out excellent code in some programming system that seems pointless or even downright unusable to me.
I think different people just think differently, and if you are not tempted by syntactic sugar or especially abstractions that only exist for convenience and actually have a significant runtime cost, then by all means stay away from such languages.
I would however recommend that you at least try to familiarise yourself with the concepts that you're giving up. I have nothing against someone who is vehemently pro-pure-C, as long as they actually understand what the big deal is about lambda expressions. I suspect that most will not immediately become a fan, but at least it'll be there at the back of their minds when they find the perfect problem what would have been oh so much easier to solve with lambdas.
And, above all, try to avoid getting annoyed by fanboy speak, especially by people who don't actually know what they're talking about.
Haskell enforces Referential Transparency: given the same parameters, every function always returns the same result, no matter how many times you call that function.
That means, for example, that on Haskell (and without Monads) you can not implement a random number generator. In C++ or Java you can do that using global variables, storing the intermediate "seed" value of the random generator.
On Haskell the counterpart of global variables are Monads.
Kind of an old question but it's a really good one, so I'll answer.
You can think of monads as blocks of code for which you have complete control over how they're executed: what each line of code should return, whether the execution should stop at any point, whether some other processing should happen between each line.
I'll give some examples of things that monads enable that would be difficult otherwise. None of these examples are in Haskell, just because my Haskell knowledge is a bit shaky, but they're all examples of how Haskell has inspired the use of monads.
Normally, if you wanted to write a parser of some sort, say to implement a programming language, you would have to either read the BNF specification and write a whole bunch of loopy code to parse it, or you would have to use a compiler compiler like Flex, Bison, yacc etc.. But with monads, you can make a kind of "compiler parser" right in Haskell.
Parsers can't really be done without either monads or special-purpose languages like yacc, bison etc.
For instance, I took the BNF language specification for the IRC protocol:
And crunched it down to about 40 lines of code in F# (which is another language that supports monads):
F#'s monad syntax is quite ugly compared to Haskell's, and I could likely have improved this quite a bit -- but the point to take home is that structurally, the parser code is identical to the BNF. Not only would this have taken a lot more work without monads (or a parser generator), it would have had almost no resemblance to the specification, and thus been terrible both to read and to maintain.
Normally, multitasking is thought of as being an OS feature -- but with monads, you can write your own scheduler such that after each instruction monad, the program would pass control over to the scheduler, which would then choose another monad to execute.
One guy made a "task" monad to control game loops (again in F#), so that instead of having to write everything as a state machine that acts on each
In other words, instead of having to do something like:
You could do something like:
LINQ to SQL
LINQ to SQL is actually an example of a monad, and similar functionality could easily be implemented in Haskell.
I won't get into the details since I don't remember all that accurately, but Erik Meijer explains it quite well.
If you're familiar with the GoF patterns, monads are like the Decorator pattern and Builder pattern put together, on steroids, bitten by a radioactive badger.
There are better answers up above, but some of the specific benefits I see are:
A familiar example of a monad in Java is List. It takes some core class, like String, and "lifts" it into the monad space of List, adding information about the list. Then it binds new functions into that space like get(), getFirst(), add(), empty(), etc.
On the large scale, imagine that instead of writing a program, you just wrote a big Builder (as the GoF pattern), and the build() method at the end spat out whatever answer the program was supposed to produce. And that you could add new methods to your ProgramBuilder without recompiling the original code. That's why monads are a powerful design model.