I don't find this true at all. Haskell exceptions don't look like exceptions in other languages, so it's easy to get hung up on the fact that error is generally used only for unrecoverable errors. But that's why it's called error, not exception. In Haskell, Either and Maybe are used where I would normally use try/except in Python.
The only exception to this that I've found is that error is something you may need to deal with in the IO monad, where in Python it would still be handled via exceptions.
Well, I didn't think of Maybe and Either as exceptions, but rather considered undefined/error. The exceptions from Control.Exception are probably the closest to exceptions in other languages, and I think those are built on error.
In C++, use exceptions when things go so badly that you have to metaphorically pack things up and send some people home. Because that's what exceptions are good at.
For example, I used to work on a system where there were various threads each controlling a different piece of hardware. But the hardware was hot-swapable, so it was possible that suddenly a thread would find itself trying to talk to hardware that was no longer there. We would throw an exception at the low level hardware access point, at catch at the (nearly) highest level of the thread. This allowed us to reclaim memory and other resources used by the thread in an orderly fashion, and return to a "ready for hardware insert" mode. This was key since the other threads were doing just fine and the overall program needed to continue.
Certainly not. In Python, for example, exceptions are used to handle exceptional conditions.
Here's an example. Say I'm writing a function and I have a dictionary I need to access values from often. Now say that 85% of the time the key I need is in the dictionary, but 15% of the time it is not. I could do this:
if key in my_dict:
execute_operation(my_dict[key])
else:
pass
So that if the key is not in the dictionary I do nothing. But this can be expressed more clearly like this:
This is considered to be clearer because it expresses the fact that the key should be in the dictionary, but in some cases is not. And interestingly, performance reflects this. The first method is more efficient in cases where the key is usually not in the dictionary. The second method, on the other hand, is more efficient when the key is usually present in the dictionary.
So, in summary, exceptions are used in Python to represent cases where successfully executing the code within the try block is normal, but exceptional conditions could once in awhile occur. Almost all uses of exceptions occur for conditions where the program should not crash. When the program should crash we just let the exception bubble up to the top level where we gracefully shut down the program and call an exit function.
Unfortunately, the second one eats an uncaught KeyError raised deep inside execute_operation, not just my_dict[key] failing. Which may be easy to overcome if you wrote all the code and libraries that execute_operation calls, but nearly impossible otherwise.
As a C programer i consider the first method to be clearer and am still unconvinced that exceptions should be user for anything other than unrecoverable errors; exceptions have the stack unwinding feature.
The only exception to this that I've found is that error is something you may need to deal with in the IO monad, where in Python it would still be handled via exceptions.