If I understood rightly, exceptions in Haskell basically intended to deal within IO monad. At least exception could be caught inside IO monad.
But sometimes even pure functions may throw an exception, e.g. read "..." :: Int (when reading string does not represent integer), operator (!!) (when we trying to get item out of range of the list), and so forth. And this is true behavior, I don’t deny. However, I would not want to change signature of function just to get it chance to catch possible exception, because in this case I have to change signature all the functions by call stack before.
Is there some pattern to deal with exceptions more comfortable in Haskell, out of IO monad? May be I should use unsafePerformIO in this case? How “safe” to use unsafePerformIO just for catching exceptions in pure functions?
In pure code, it’s usually best to avoid exceptions from happening in the first place. That is, don’t use
headunless you’re absolutely positive that the list isn’t empty, and usereadsand pattern matching instead ofreadto check for parse errors.I think a good rule of thumb is that exceptions in pure code should only come from programming errors, i.e. calls to
error, and these should be treated as bugs, not something an exception handler can deal with.Note that I’m only talking about pure code here, exceptions in
IOhave their uses when dealing with the exceptional cases that sometimes happen when interfacing with the “real world”. However, pure mechanisms likeMaybeandErrorTare easier to work with, so they are often preferred.