Comment by mattalex
6 hours ago
Of course you can: you just have to define it in your type. The output set becomes a union type of the normal output and whatever you want as an exception.
If you write this as a monad, your get very similar syntax to procedural code.
I get what you are saying, but…
An exception is different to an Either result type. Exceptions short circuit execution and walk up the call tree to the nearest handler. They also have very different optimization in practice (eg in C++)
I'm what way is that different? You return early and the call Cascades up the call chain until you handle it (otherwise it's always an "either" results)
In practice you use something like an exception monad, which makes this a lot more ergonomic since you don't need to carry a case distinction around for every unwrap: an exception monad essentially has an implicit passthrough that says "if it's a value, apply the function, if it's an exception just keep that". You only need to "catch" the exception if you actually need the value. I'm this case the exception monad is not that different from annotating a function with "throws": your calling function either needs it's own throws (=error monad wrapper) in which case exceptions just roll through, or you remove the throws, but now need to handle the exception explicitly (=unwrap the monad).