A variant of throw that can be used within the IO monad.
Although ioError has a type that is an instance of the type of throw, the
two functions are subtly different:
throw e `seq` return () ===> throw e
ioError e `seq` return () ===> return ()
The first example will cause the exception e to be raised,
whereas the second one won't. In fact, ioError will only cause
an exception to be raised when it is used within the IO monad.
The ioError variant should be used in preference to throw to
raise an exception within the IO monad because it guarantees
ordering with respect to other IO operations, whereas throw
does not.