When you program in normal languages, you have the ability to perform effects all of the time. You can always read/write to/from files, you can always raise exceptions or otherwise change the control flow. There's nothing you can't do.
Haskell is different. In Haskell, by default, you don't have any effects at your disposal at all. You can create values from other values, that's it. When you want to program with effects, you use a monad. The type of monad that you use decides the effects that you are allowed. For example, the maybe monad instance gives you the "fail without an error effect". The either monad gives you the "fail with an error effect". The list monad instance gives you the non-determinism effect. etc. You might expect me to say that IO gives you the "interact with the outside world effect", but that's not really true, forget what you know about IO for the moment.
The continuation monad instance is a bit special. In a sense, it is the most general of the monad types, because every monad instance can be seen as a specialization of it. The continuation monad allows every kind of effect. At this point, you might be thinking, "but how can this be, it doesn't allow IO".
To reconcile these facts. I present the coroutine monad. It has an effect, yield, that gives a value to the caller and waits for the caller to respond with a value so that it can continue. Here are some types:
runCoroutine :: Coroutine i o x -> Either (o, i -> Coroutine i o x) x
yield :: o -> Coroutine i o i
So running a coroutine either produces a value of o and function to resume the coroutine or it completes with a value of x. IO is very similar to the coroutine monad. When a Haskell program gets to a function that talks to the outside world it yields control to the runtime environment, the runtime environment does the actual IO and passes the result back so that the program can continue.This is why Haskell is pure despite having effects. Haskell programs don't do IO, they yield control to the runtime environment whenever IO needs to be done.
So why are monads useful? They allow you to restrict the effects that are possible in different parts of your programs. This aids in reasoning about your programs, because you don't have to think about whole classes of behaviour, but they're less useful in other languages where you already have effects everywhere.