
Disclaimer: I'm explaining all of this in terms of "actions", which are only one way of looking at monads, and the view only works for certain ones (IO, State, ...). Without futher ado... An action does two things: it has a side-effect and then it has a return value. The type "IO Int" is an I/O action which does something then returns an Int. (>>) :: m a -> m b -> m b x >> y first does x, *discards* its return value, then does y. You can see that the return value of x is discarded by the absence of the type variable a in the return value of (>>). So if you said: getLine >> putStrLn "Hello" This is an action which gets a line from the user and then throws it away, never to be retrieved again, only to print Hello. (>>=) :: m a -> (a -> m b) -> m b But what if you want to do something with the return value? That's what (>>=) is for. (>>=) takes an action on its left side and a function which returns an action on its right, and then "pipes" one into the other. getLine >>= (\x -> putStrLn x) This gets a line from the user and then executes the function on the right given the return value from getLine as an argument; i.e. x is bound to the return value of getLine. The above can also be written as: getLine >>= putStrLn Because of currying. This action echoes one line. Using this you can do more complex actions, like, for instance, adding two numbers: readLine >>= (\x -> readLine >>= (\y -> print (x + y))) Take a moment to grok that... Which you might like to write: do x <- readLine y <- readLine print (x + y) The parser sequencing thing is probably from the List monad (unless you're using Parsec or something). List was the first monad I really understood (before IO even), thanks to this great tutorial: http://www.haskell.org/haskellwiki/Monads_as_containers Luke