Ответ 1
Одной из причин является денотационная семантика Haskell.
Одной из опрятных свойств (чистых) функций Haskell является их монотонность - более определенный аргумент дает более определенное значение. Это свойство очень важно, например, рассуждать о рекурсивных функциях (прочитайте статью, чтобы понять, почему).
Обозначение исключения по определению - нижний, _|_
, наименьший элемент в poset, соответствующий данному типу. Таким образом, для удовлетворения требования монотонности для любого обозначения f
функции Хаскеля должно выполняться следующее неравенство:
f(_|_) <= f(X)
Теперь, если бы мы могли перехватывать исключения, мы могли бы разбить это неравенство на "распознавание" дна (перехват исключения) и возврат более определенного значения:
f x = case catch (seq x True) (\exception -> False) of
True -> -- there was no exception
undefined
False -> -- there was an exception, return defined value
42
Здесь полная рабочая демонстрация (требуется базовый 4 Control.Exception):
import Prelude hiding (catch)
import System.IO.Unsafe (unsafePerformIO)
import qualified Control.Exception as E
catch :: a -> (E.SomeException -> a) -> a
catch x h = unsafePerformIO $ E.catch (return $! x) (return . h)
f x = case catch (seq x True) (\exception -> False) of
True -> -- there was no exception
undefined
False -> -- there was an exception, return defined value
42
Другая причина, как отметил TomMD, заключается в нарушении ссылочной прозрачности. Вы можете заменить равные вещи равными и получить другой ответ. (Равно в денотационном смысле, т.е. Они обозначают одно и то же значение, а не в значении ==
).
Как мы это сделаем? Рассмотрим следующее выражение:
let x = x in x
Это нерекурсивная рекурсия, поэтому она никогда не возвращает нам никакой информации и поэтому также обозначается символом _|_
. Если бы мы могли поймать исключения, мы могли бы написать функцию f, такую как
f undefined = 0
f (let x = x in x) = _|_
(Последнее всегда верно для строгих функций, потому что Haskell не предоставляет никаких средств для обнаружения не заканчивающихся вычислений - и не может в принципе, из-за Halting проблема.)