Как работает обработка исключений Haskell?

foldl1 (+) []

Как я могу получить полученную ошибку?

Ответ 1

Чистый код может вызывать асинхронный, неточные исключения, например, когда частичная функция встречает ввод, к которому не имеет дело.

Это логические ошибки, обычно указывающие на ошибки в спецификации программы.

Они могут быть пойманы в коде ввода-вывода (обычно на внешнем уровне программы) с помощью обработчика исключений.

Например, чтобы уловить недостающий код для пустого списка,

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns        #-}

import Control.Exception

main = do
    handle (\(e :: SomeException) -> print $ "This program as a bug: " ++ show e) $ do
        let !v = foldl1 (+) ([] :: [Int])
        return ()

Мы можем заметить, что исключение поймано, и программа завершается.

$ ./A
"This program as a bug: Prelude.foldl1: empty list"

Ответ 3

Ответ пуриста: результат undefined (в частности, bottom). Вы ничего не можете с этим сделать, кроме сбоя, если значение используется каким-либо образом для создания результатов программы. См. Haskell 98 Report section 3.1. Он указывает, что такие "ошибки вызывают немедленное завершение программы и не могут быть уловлены пользователем".

Лучше всего проверять входные значения и обрабатывать их, прежде чем они смогут получить это. Не используйте fold1, если список может содержать 0 элементов.

На практике, однако, вы можете использовать методы в других ответах, чтобы поймать его в IO при использовании GHC. Исключения не могут быть пойманы в чистом (не-IO) коде, потому что повышение исключения - это изменение в потоке управления, это побочный эффект, а не чистое вычисление.