I concede on the pseudocode formatting point. Upon rereading, that is uglier than necessary.
The trouble with exceptions is that, unless you're referring to Java-style checked exceptions, there's nothing that forces you to handle them. You can still forget that the exception can occur, and then your code will blow up at runtime. And in one sense, exceptions are even worse than the repetitive if-then clauses: if statements at least handle the failure right there at the call site, whereas exceptions let you move your error handling code to some other place in the call stack, non-local to where the actual error might occur. There are advantages as well, for sure, but I see this as potentially very confusing.
Haskell has exceptions but most people prefer to avoid them, favoring the use of MonadError instances (such as Maybe) instead, since they make the potential failure highly explicit and impossible to forget about or ignore. And while I don't think using Maybe is at all the same as ignoring errors, I suppose I see how it could be construed that way. That's why there's Either as well, which allows you to associate some piece of data with the failure. So you could use the Either String monad to pass back an error message on failure, or Either [String] to pass a list of them, or Either (IO ()) to specify an action to be taken in response to the failure, or whatever you want. I guess that ends up being a lot like exceptions, except for the fact that you can't ignore or forget them, so your code is still verifiably safe at runtime, and there is nice syntactic sugar from the Monad class (do notation, >>= chaining, etc.) to make them concise and elegant to use without cluttering your code.
The trouble with exceptions is that, unless you're referring to Java-style checked exceptions, there's nothing that forces you to handle them. You can still forget that the exception can occur, and then your code will blow up at runtime. And in one sense, exceptions are even worse than the repetitive if-then clauses: if statements at least handle the failure right there at the call site, whereas exceptions let you move your error handling code to some other place in the call stack, non-local to where the actual error might occur. There are advantages as well, for sure, but I see this as potentially very confusing.
Haskell has exceptions but most people prefer to avoid them, favoring the use of MonadError instances (such as Maybe) instead, since they make the potential failure highly explicit and impossible to forget about or ignore. And while I don't think using Maybe is at all the same as ignoring errors, I suppose I see how it could be construed that way. That's why there's Either as well, which allows you to associate some piece of data with the failure. So you could use the Either String monad to pass back an error message on failure, or Either [String] to pass a list of them, or Either (IO ()) to specify an action to be taken in response to the failure, or whatever you want. I guess that ends up being a lot like exceptions, except for the fact that you can't ignore or forget them, so your code is still verifiably safe at runtime, and there is nice syntactic sugar from the Monad class (do notation, >>= chaining, etc.) to make them concise and elegant to use without cluttering your code.