Earlier quoted context omitted.
Haskell has been around for over 20 years. If it hasn't set the programming world on fire yet, there are probably reasons.
Haskell definitely has problems. I'm a huge fan of the language, but I think its disingenuous to pretend like its flawless. To name a few: 1. Poor debugging tools. Unfortunately this is sort of intrinsically tied with non-strict evaluation. Typical evaluation stepping debuggers would be sort of unpredictable in haskell. Along these lines, haskell doesn't have stack traces enabled by default, and reading them is sort…
So far as I'm aware, there is no technical difference between exceptions thrown in IO versus exceptions thrown in pure code. There are two contextual differences.
First, exceptions can only be caught in IO, but everything running has IO above it somewhere, or it wouldn't be running in the first place.
Regarding exceptions thrown in IO versus elsewhere, it's worth noting that exceptions thrown anywhere are only actually thrown if the thunk representing them is forced. IO values tend to be used quite close to where they are created, whereas an exception in lazy, pure code might hide in the creation of the leaf of a tree or at the end of a list.