Why is the raising of an exception a side effect?

Purity is only violated if you observe the exception, and make a decision based on it that changes the control flow. Actually throwing an exception value is referentially transparent — it is semantically equivalent to non-termination or other so-called bottom values.

If a (pure) function is not total, then it evaluates to a bottom value. How you encode the bottom value is up to the implementation – it could be an exception; or non-termination, or dividing by zero, or some other failure.

Consider the pure function:

 f :: Int -> Int
 f 0 = 1
 f 1 = 2

This is not defined for all inputs. For some it evaluates to bottom. The implementation encodes this by throwing an exception. It should be semantically equivalent to using a Maybe or Option type.

Now, you only break referential transparency when you observe the bottom value, and make decisions based on it — which could introduce non-determinism as many different exceptions may be thrown, and you can’t know which one. So for this reason catching exceptions is in the IO monad in Haskell, while generating so-called “imprecise” exceptions can be done purely.

So it is just not true that raising an exception is a side effect as such. It is whether or not you can modify the behavior of a pure function based on an exceptional value — thus breaking referential transparency — that is the issue.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)