A Haskell program is a world remaking function whose component parts are world remaking functions. Here is an example.
The functions be_nice, say_hello, and main can all be seen as having this type
The function (>>) combines say_hello and be_nice to create main. We can view its type signature as
Think of (>>) as “then” because we are talking about one world changing action after another. Leaving aside, for the moment, precisely how (>>) works, we can understand how to get sequentiality within a functional paradigm by imagining that our program has been defined this way
Only we cannot write it that way because Haskell abstracts the concept of world away from the programmer.
A Haskell programmer is more concerned with creating a program than with remaking worlds. In fact, the world is full of things the Haskell programmer ought not be playing with. So it is better to make (>>) apply to some simple data type than to make it refer to world remaking functions. Haskell provides a parameterized type, IO a for this purpose. As an examples
The type for (>>) is
This is much simpler than the version above which uses world remaking functions. Moreover this is Haskell.
You may have noticed that IO needs a parameter before it becomes a real type. Such a thing is usually called a “parameterized” type. I prefer to think of it as a meta type. I will discuss the purpose of this parameter in Section III.
Another way to think of IO is that it is a type constructor. Give it an argument and it constructs a type. In sections Section VIII and Section IX you will see a use for monad type constructors that take more than one parameter.
The IO meta type is known as a monad. The concept of monad is useful because it emphasizes certain similarities between otherwise different parts of our programs. These similarities give us a framework in which to understand new things. Once you get used to the framework, it helps with the understanding.
One way to think of a monad m is to see it as a workshop in which we can create and work with objects of type m a.
All monadic workshops m have a (>>) function. Its general type is
and it is often called a “combinator”. The type signature for (>>) particularizes to
in the IO monad.
I use the term “object” for anything a Haskell program can manipulate. This includes functions. Objects whose type is of the form m a where m is a monad I will call “monadic objects”.
Although the syntax requirements for (>>) are the same in all workshops, the behavior of (>>) differs. One way to think of this would be to imagine that each workshop exists in its own universe with its own physical laws. This of course would imply that the (>>) you see in one workshop wouldn't necessarily behave the same as in another. It does not imply that the physical laws within any one workshop are completely arbitrary. As you read on, you will see that the similarities between one monad and another go deeper than mere syntax.
Each workshop has its own tools for manipulating its objects. The (>>) combinator is only one of four that must be present in all workshops.