Spec-Zone.ru › Haskell 8

Control.Exception

Авторские права (c) Университет Глазго 2001
Лицензия BSD-стиля (см. файл libraries/base/LICENSE)
Поддерживающий libraries@haskell.org
Стабильность экспериментальная
Переносимость непереносимая (расширенные исключения)
Безопасный Haskell Надежный
Язык Haskell2010

Содержание

  • Тип исключения
  • Выбрасывание исключений
  • Обработка исключений
    • Обработка всех исключений
    • Функции catch
    • Функции handle
    • Функции try
    • Функция evaluate
    • Функция mapException
  • Асинхронные исключения
    • Управление асинхронными исключениями
      • Применение mask к обработчику исключений
      • Прерывимые операции
  • Утверждения
  • Утилиты

Описание

Этот модуль предоставляет поддержку для повышения и обработки встроенных и пользовательских исключений.

Помимо исключений, выбрасываемых IO операциями, исключения могут быть выброшены чистым кодом (неточные исключения) или внешними событиями (асинхронные исключения), но могут быть пойманы только в IO монаде. Для получения более подробной информации см.:

  • Семантика неточных исключений, Саймон Пейтон Джонс, Аласдейр Рейд, Тони Хоар, Саймон Марлоу, Фергус Хендерсон, в PLDI'99.
  • Асинхронные исключения в Haskell, Саймон Марлоу, Саймон Пейтон Джонс, Энди Моран и Джон Реппи, в PLDI'01.
  • Расширяемая динамически типизированная иерархия исключений, Саймон Марлоу, в Haskell '06.

Тип исключения

data SomeException Источник

Тип SomeException является корнем иерархии типов исключений. При выбросе исключения типа e, в скрытом виде оно инкапсулируется в SomeException.

Конструкторы

forall e.Исключение e => SomeException e
Примеры
Подробности примеров
Show SomeException

С момента: base-3.0

Подробности примера

Определено в GHC.Exception.Type

Методы

showsPrec :: Int -> SomeException -> ShowS Источник

show :: SomeException -> Строка Источник

showList :: [SomeException] -> ShowS Источник

Исключение SomeException

С момента: base-3.0

Подробности примера

Определено в GHC.Exception.Type

Методы

toException :: SomeException -> SomeException Источник

fromException :: SomeException -> Возможно SomeException Источник

displayException :: SomeException -> Строка Источник

class (Typeable e, Show e) => Исключение e where Источник

Любой тип, который вы хотите бросить или поймать как исключение, должен быть экземпляром класса Exception. Простейший случай — новый тип исключения непосредственно под корнем:

data MyException = ThisException | ThatException
    deriving Show

instance Exception MyException

Определения по умолчанию в классе Exception делают то, что нам нужно в этом случае. Теперь вы можете выбрасывать и ловить ThisException и ThatException как исключения:

*Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
Caught ThisException

В более сложных примерах вы можете определить целую иерархию исключений:

---------------------------------------------------------------------
-- Make the root exception type for all the exceptions in a compiler

data SomeCompilerException = forall e . Exception e => SomeCompilerException e

instance Show SomeCompilerException where
    show (SomeCompilerException e) = show e

instance Exception SomeCompilerException

compilerExceptionToException :: Exception e => e -> SomeException
compilerExceptionToException = toException . SomeCompilerException

compilerExceptionFromException :: Exception e => SomeException -> Maybe e
compilerExceptionFromException x = do
    SomeCompilerException a <- fromException x
    cast a

---------------------------------------------------------------------
-- Make a subhierarchy for exceptions in the frontend of the compiler

data SomeFrontendException = forall e . Exception e => SomeFrontendException e

instance Show SomeFrontendException where
    show (SomeFrontendException e) = show e

instance Exception SomeFrontendException where
    toException = compilerExceptionToException
    fromException = compilerExceptionFromException

frontendExceptionToException :: Exception e => e -> SomeException
frontendExceptionToException = toException . SomeFrontendException

frontendExceptionFromException :: Exception e => SomeException -> Maybe e
frontendExceptionFromException x = do
    SomeFrontendException a <- fromException x
    cast a

---------------------------------------------------------------------
-- Make an exception type for a particular frontend compiler exception

data MismatchedParentheses = MismatchedParentheses
    deriving Show

instance Exception MismatchedParentheses where
    toException   = frontendExceptionToException
    fromException = frontendExceptionFromException

Теперь мы можем перехватить исключение MismatchedParentheses как MismatchedParentheses, SomeFrontendException или SomeCompilerException, но не других типов, например, IOException.

*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException))
*** Exception: MismatchedParentheses

Минимальное полное определение

Ничего

Методы

toException :: e -> SomeException Источник

fromException :: SomeException -> Возможно e Источник

displayException :: e -> Строка Источник

Отобразить значение этого исключения в удобочитаемом виде.

Реализация по умолчанию: show.

С момента: base-4.8.0.0

Примеры
Подробности примеров
Исключение НекоторыеИсключения

С момента: base-3.0

Подробности примера

Определено в GHC.Exception.Type

Методы

toException :: НекоторыеИсключения -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть НекоторыеИсключения Исходный код

displayException :: НекоторыеИсключения -> Строка Исходный код

Исключение АрифметическоеИсключение

С момента: base-4.0.0.0

Подробности примера

Определено в GHC.Exception.Type

Методы

toException :: АрифметическоеИсключение -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть АрифметическоеИсключение Исходный код

displayException :: АрифметическоеИсключение -> Строка Исходный код

Исключение ВызовОшибки

С момента: base-4.0.0.0

Подробности примера

Определено в GHC.Exception

Методы

toException :: ВызовОшибки -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть ВызовОшибки Исходный код

displayException :: ВызовОшибки -> Строка Исходный код

Исключение FileLockingNotSupported
Подробности примера

Определено в GHC.IO.Handle.Lock.Common

Методы

toException :: FileLockingNotSupported -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть FileLockingNotSupported Исходный код

displayException :: FileLockingNotSupported -> Строка Исходный код

Исключение IOException

С момента: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: IOException -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть IOException Исходный код

displayException :: IOException -> Строка Исходный код

Исключение КодВыхода

С момента: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: КодВыхода -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть КодВыхода Исходный код

displayException :: КодВыхода -> Строка Исходный код

Исключение FixIOException

С момента: base-4.11.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: FixIOException -> SomeException Исходный код

fromException :: SomeException -> Maybe FixIOException Исходный код

displayException :: FixIOException -> Строка Исходный код

Исключение ArrayException

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: ArrayException -> SomeException Исходный код

fromException :: SomeException -> Maybe ArrayException Исходный код

displayException :: ArrayException -> Строка Исходный код

Исключение AsyncException

С момента: base-4.7.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: AsyncException -> SomeException Исходный код

fromException :: SomeException -> Maybe AsyncException Исходный код

displayException :: AsyncException -> Строка Исходный код

Исключение SomeAsyncException

С момента: base-4.7.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: SomeAsyncException -> SomeException Исходный код

fromException :: SomeException -> Maybe SomeAsyncException Исходный код

displayException :: SomeAsyncException -> Строка Исходный код

Исключение AssertionFailed

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: AssertionFailed -> SomeException Исходный код

fromException :: SomeException -> Maybe AssertionFailed Исходный код

displayException :: AssertionFailed -> Строка Исходный код

Исключение CompactionFailed

С момента: base-4.10.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: CompactionFailed -> SomeException Исходный код

fromException :: SomeException -> Maybe CompactionFailed Исходный код

displayException :: CompactionFailed -> Строка Исходный код

Исключение AllocationLimitExceeded

С момента: base-4.8.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: Превышение лимита выделения памяти -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно Превышение лимита выделения памяти Исходный код

displayException :: Превышение лимита выделения памяти -> Строка Исходный код

Исключение Тупик

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: Тупик -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно Тупик Исходный код

displayException :: Тупик -> Строка Исходный код

Исключение Заблокирован на неопределенное время в STM

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: Заблокирован на неопределенное время в STM -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно Заблокирован на неопределенное время в STM Исходный код

displayException :: Заблокирован на неопределенное время в STM -> Строка Исходный код

Исключение Заблокирован на неопределенное время на MVar

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: Заблокирован на неопределенное время на MVar -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно Заблокирован на неопределенное время на MVar Исходный код

displayException :: Заблокирован на неопределенное время на MVar -> Строка Исходный код

Исключение Динамический

С момента: base-4.0.0.0

Подробности экземпляра

Определено в Data.Dynamic

Методы

toException :: Динамический -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно Динамический Исходный код

displayException :: Динамический -> Строка Исходный код

Исключение ВложенноАтомарно

С момента: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: ВложенноАтомарно -> НекоторыйИсключение Исходный код

fromException :: НекоторыйИсключение -> Возможно ВложенноАтомарно Исходный код

displayException :: ВложенноАтомарно -> Строка Исходный код

Исключение Непрерывность

С момента: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: NonTermination -> SomeException Исходный код

fromException :: SomeException -> Maybe NonTermination Исходный код

displayException :: NonTermination -> String Исходный код

Exception TypeError

Since: base-4.9.0.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: TypeError -> SomeException Исходный код

fromException :: SomeException -> Maybe TypeError Исходный код

displayException :: TypeError -> String Исходный код

Exception NoMethodError

Since: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: NoMethodError -> SomeException Исходный код

fromException :: SomeException -> Maybe NoMethodError Исходный код

displayException :: NoMethodError -> String Исходный код

Exception RecUpdError

Since: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: RecUpdError -> SomeException Исходный код

fromException :: SomeException -> Maybe RecUpdError Исходный код

displayException :: RecUpdError -> String Исходный код

Exception RecConError

Since: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: RecConError -> SomeException Исходный код

fromException :: SomeException -> Maybe RecConError Исходный код

displayException :: RecConError -> String Исходный код

Exception RecSelError

Since: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: RecSelError -> SomeException Исходный код

fromException :: SomeException -> Maybe RecSelError Исходный код

displayException :: RecSelError -> String Исходный код

Exception PatternMatchFail

Since: base-4.0

Подробности экземпляра

Определено в Control.Exception.Base

Методы

toException :: НеудавшийсяПодстановочныйПоиск -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть НеудавшийсяПодстановочныйПоиск Исходный код

displayException :: НеудавшийсяПодстановочныйПоиск -> Строка Исходный код

Исключение Таймаут

С момента: base-4.7.0.0

Подробности экземпляра

Определено в System.Timeout

Методы

toException :: Таймаут -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть Таймаут Исходный код

displayException :: Таймаут -> Строка Исходный код

Исключение Пустота

С момента: base-4.8.0.0

Подробности экземпляра

Определено в Data.Void

Методы

toException :: Пустота -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть Пустота Исходный код

displayException :: Пустота -> Строка Исходный код

data ИсключениеIO Исходный код

Исключения, возникающие в IO монаде. IOException записывает более конкретный тип ошибки, описательную строку и, возможно, дескриптор, используемый при возникновении ошибки.

Экземпляры
Подробности экземпляров
Равно ИсключениеIO

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

(==) :: ИсключениеIO -> ИсключениеIO -> Булево Исходный код

(/=) :: ИсключениеIO -> ИсключениеIO -> Булево Исходный код

Вывод ИсключениеIO

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

showsPrec :: Целое число -> ИсключениеIO -> ВыводS Исходный код

show :: ИсключениеIO -> Строка Исходный код

showList :: [ИсключениеIO] -> ВыводS Исходный код

Исключение ИсключениеIO

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: ИсключениеIO -> НекоторыеИсключения Исходный код

fromException :: НекоторыеИсключения -> МожетБыть ИсключениеIO Исходный код

displayException :: ИсключениеIO -> Строка Исходный код

data АрифметическоеИсключение Исходный код

Арифметические исключения.

Конструкторы

Переполнение
Подпотоки
ПотеряТочности
ДелениеНаНоль
Денормализация
НольЗнаменатель

С момента: base-4.6.0.0

Примеры
Подробности примеров
Eq ArithException

С момента: base-3.0

Подробности примера

Определено в GHC.Exception.Type

Методы

== :: ArithException -> ArithException -> Bool Источник

/= :: ArithException -> ArithException -> Bool Источник

Ord ArithException

С момента: base-3.0

Подробности примера

Определено в GHC.Exception.Type

Методы

compare :: ArithException -> ArithException -> Ordering Источник

< :: ArithException -> ArithException -> Bool Источник

<= :: ArithException -> ArithException -> Bool Источник

> :: ArithException -> ArithException -> Bool Источник

>= :: ArithException -> ArithException -> Bool Источник

max :: ArithException -> ArithException -> ArithException Источник

min :: ArithException -> ArithException -> ArithException Источник

Show ArithException

С момента: base-4.0.0.0

Подробности примера

Определено в GHC.Exception.Type

Методы

showsPrec :: Int -> ArithException -> ShowS Источник

show :: ArithException -> String Источник

showList :: [ArithException] -> ShowS Источник

Исключение ArithException

С момента: base-4.0.0.0

Подробности примера

Определено в GHC.Exception.Type

Методы

toException :: ArithException -> SomeException Источник

fromException :: SomeException -> Maybe ArithException Источник

displayException :: ArithException -> String Источник

data ArrayException Источник

Исключения, сгенерированные операциями с массивами

Конструкторы

IndexOutOfBounds String

Попытка индексирования массива за пределами объявленных границ.

UndefinedElement String

Попытка вычисления элемента массива, который не был инициализирован.

Примеры
Подробности примеров
Eq ArrayException

С момента: base-4.2.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

(==) :: ArrayException -> ArrayException -> Bool Исходный код

(/=) :: ArrayException -> ArrayException -> Bool Исходный код

Ord ArrayException

С момента: base-4.2.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

compare :: ArrayException -> ArrayException -> Ordering Исходный код

(<) :: ArrayException -> ArrayException -> Bool Исходный код

(<=) :: ArrayException -> ArrayException -> Bool Исходный код

(>) :: ArrayException -> ArrayException -> Bool Исходный код

(>=) :: ArrayException -> ArrayException -> Bool Исходный код

max :: ArrayException -> ArrayException -> ArrayException Исходный код

min :: ArrayException -> ArrayException -> ArrayException Исходный код

Show ArrayException

С момента: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> ArrayException -> ShowS Исходный код

show :: ArrayException -> String Исходный код

showList :: [ArrayException] -> ShowS Исходный код

Исключение ArrayException

С момента: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: ArrayException -> SomeException Исходный код

fromException :: SomeException -> Может быть ArrayException Исходный код

displayException :: ArrayException -> Строка Исходный код

newtype ОшибкаУтверждения Исходный код

assert было применено к False.

Конструкторы

ОшибкаУтверждения Строка
Примеры реализации
Подробности примеров реализации
Show AssertionFailed

С момента выпуска: base-4.1.0.0

Подробности реализации

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> AssertionFailed -> ShowS Исходный код

show :: AssertionFailed -> String Исходный код

showList :: [AssertionFailed] -> ShowS Исходный код

Исключение AssertionFailed

С момента выпуска: base-4.1.0.0

Подробности реализации

Определено в GHC.IO.Exception

Методы

toException :: AssertionFailed -> SomeException Исходный код

fromException :: SomeException -> Может быть AssertionFailed Исходный код

displayException :: AssertionFailed -> String Исходный код

тип SomeAsyncException Исходный код

Базовый класс для асинхронных исключений.

С момента выпуска: base-4.7.0.0

Конструкторы

forall e.Исключение e => SomeAsyncException e
Примеры реализации
Подробности примеров реализации
Show SomeAsyncException

С момента выпуска: base-4.7.0.0

Подробности реализации

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> SomeAsyncException -> ShowS Исходный код

show :: SomeAsyncException -> Строка Исходный код

showList :: [SomeAsyncException] -> ShowS Исходный код

Исключение SomeAsyncException

С момента выпуска: base-4.7.0.0

Подробности реализации

Определено в GHC.IO.Exception

Методы

toException :: SomeAsyncException -> SomeException Исходный код

fromException :: SomeException -> Может быть SomeAsyncException Исходный код

displayException :: SomeAsyncException -> Строка Исходный код

тип AsyncException Исходный код

Асинхронные исключения.

Конструкторы

Переполнение стека

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

Переполнение кучи

Память кучи программы приближается к своему лимиту, и программа должна принять меры, чтобы уменьшить количество активных данных. Примечания:

  • Неопределено, какая нить получит это исключение. В настоящее время GHC бросает это в ту же нить, что и UserInterrupt, но это может измениться в будущем.
  • В настоящее время GHC RTS может восстановиться только от переполнения кучи, если он обнаружит, что был превышен явный лимит памяти (установленный с помощью флагов RTS). В настоящее время невозможность выделения памяти из операционной системы приводит к немедленному завершению программы.
Уничтожение нити

Это исключение вызывается другой нитью, вызывающей killThread, или системой, если ей необходимо завершить нить по какой-либо причине.

Прерывание пользователя

Это исключение по умолчанию генерируется в основной нити программы, когда пользователь запрашивает завершение программы с помощью стандартного механизма (например, сочетания клавиш Control-C в консоли).

Примеры
Подробности примеров
Eq AsyncException

С момента: base-4.2.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

(==) :: AsyncException -> AsyncException -> Bool Исходный код

(/=) :: AsyncException -> AsyncException -> Bool Исходный код

Ord AsyncException

С момента: base-4.2.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

compare :: AsyncException -> AsyncException -> Ordering Исходный код

(<) :: AsyncException -> AsyncException -> Bool Исходный код

(<=) :: AsyncException -> AsyncException -> Bool Исходный код

(>) :: AsyncException -> AsyncException -> Bool Исходный код

(>=) :: AsyncException -> AsyncException -> Bool Исходный код

max :: AsyncException -> AsyncException -> AsyncException Исходный код

min :: AsyncException -> AsyncException -> AsyncException Исходный код

Show AsyncException

С момента: base-4.1.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> AsyncException -> ShowS Исходный код

show :: AsyncException -> String Исходный код

showList :: [AsyncException] -> ShowS Исходный код

Исключение AsyncException

С момента: base-4.7.0.0

Подробности экземпляра

Определено в GHC.IO.Exception

Методы

toException :: AsyncException -> SomeException Исходный код

fromException :: SomeException -> Maybe AsyncException Исходный код

displayException :: AsyncException -> String Исходный код

asyncExceptionToException :: Исключение e => e -> SomeException Исходный код

С момента: base-4.7.0.0

asyncExceptionFromException :: Исключение e => SomeException -> Maybe e Исходный код

С момента: base-4.7.0.0

data Непрерывность Исходный код

Выбрасывается, когда система выполнения обнаруживает, что вычисление гарантированно не завершится. Обратите внимание, что нет гарантии, что система выполнения заметит, гарантированно ли завершится данное вычисление или нет.

Конструкторы

Непрерывность
Примеры использования
Подробности примеров использования
Show NonTermination

С версии: base-4.0

Подробности примера

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> NonTermination -> ShowS Исходный код

show :: NonTermination -> String Исходный код

showList :: [NonTermination] -> ShowS Исходный код

Исключение NonTermination

С версии: base-4.0

Подробности примера

Определено в Control.Exception.Base

Методы

toException :: NonTermination -> SomeException Исходный код

fromException :: SomeException -> Maybe NonTermination Исходный код

displayException :: NonTermination -> String Исходный код

data ВложенноАтомарно Исходный код

Выбрасывается, когда программа пытается вызвать atomically, из пакета stm, внутри другого вызова atomically.

Конструкторы

ВложенноАтомарно
Примеры использования
Подробности примеров использования
Show ВложенноАтомарно

С версии: base-4.0

Подробности примера

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> ВложенноАтомарно -> ShowS Исходный код

show :: ВложенноАтомарно -> String Исходный код

showList :: [ВложенноАтомарно] -> ShowS Исходный код

Исключение ВложенноАтомарно

С версии: base-4.0

Подробности примера

Определено в Control.Exception.Base

Методы

toException :: ВложенноАтомарно -> SomeException Исходный код

fromException :: SomeException -> Maybe ВложенноАтомарно Исходный код

displayException :: ВложенноАтомарно -> String Исходный код

data ЗаблокированБессрочноНаMVar Исходный код

Поток заблокирован на MVar, но других ссылок на MVar нет, поэтому он не может продолжить работу.

Конструкторы

ЗаблокированБессрочноНаMVar
Примеры
Подробности примеров
Show BlockedIndefinitelyOnMVar

С тех пор: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> BlockedIndefinitelyOnMVar -> ShowS Источник

show :: BlockedIndefinitelyOnMVar -> String Источник

showList :: [BlockedIndefinitelyOnMVar] -> ShowS Источник

Исключение BlockedIndefinitelyOnMVar

С тех пор: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: BlockedIndefinitelyOnMVar -> SomeException Источник

fromException :: SomeException -> Может быть BlockedIndefinitelyOnMVar Источник

displayException :: BlockedIndefinitelyOnMVar -> Строка Источник

data BlockedIndefinitelyOnSTM Источник

Поток ожидает повторной попытки транзакции STM, но других ссылок на любые TVar нет, поэтому он никогда не сможет продолжить.

Конструкторы

BlockedIndefinitelyOnSTM
Примеры
Подробности примеров
Show BlockedIndefinitelyOnSTM

С тех пор: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> BlockedIndefinitelyOnSTM -> ShowS Источник

show :: BlockedIndefinitelyOnSTM -> Строка Источник

showList :: [BlockedIndefinitelyOnSTM] -> ShowS Источник

Исключение BlockedIndefinitelyOnSTM

С тех пор: base-4.1.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: BlockedIndefinitelyOnSTM -> SomeException Источник

fromException :: SomeException -> Может быть BlockedIndefinitelyOnSTM Источник

displayException :: BlockedIndefinitelyOnSTM -> Строка Источник

data AllocationLimitExceeded Источник

Этот поток превысил свой лимит выделения. См. setAllocationCounter и enableAllocationLimit.

С тех пор: base-4.8.0.0

Конструкторы

AllocationLimitExceeded
Примеры
Подробности примеров
Show AllocationLimitExceeded

С момента: base-4.7.1.0

Подробности примера

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> AllocationLimitExceeded -> ShowS Исходный код

show :: AllocationLimitExceeded -> String Исходный код

showList :: [AllocationLimitExceeded] -> ShowS Исходный код

Исключение AllocationLimitExceeded

С момента: base-4.8.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

toException :: AllocationLimitExceeded -> SomeException Исходный код

fromException :: SomeException -> Maybe AllocationLimitExceeded Исходный код

displayException :: AllocationLimitExceeded -> String Исходный код

newtype CompactionFailed Исходный код

Сжатие обнаружило объект, который нельзя сжать. Функции, изменяемые объекты или закрепленные объекты сжать нельзя. См. compact.

С момента: base-4.10.0.0

Конструкторы

CompactionFailed String
Примеры
Подробности примеров
Show CompactionFailed

С момента: base-4.10.0.0

Подробности примера

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> CompactionFailed -> ShowS Исходный код

show :: CompactionFailed -> String Исходный код

showList :: [CompactionFailed] -> ShowS Исходный код

Исключение CompactionFailed

С момента: base-4.10.0.0

Подробности примера

Определено в GHC.IO.Exception

toException :: CompactionFailed -> SomeException Исходный код

fromException :: SomeException -> Maybe CompactionFailed Исходный код

displayException :: CompactionFailed -> String Исходный код

data Deadlock Исходный код

Нет запущенных потоков, поэтому программа заблокирована. Исключение Deadlock генерируется только в главном потоке.

Конструкторы

Deadlock
Примеры использования
Подробности примеров использования
Show Deadlock

С момента выпуска: base-4.1.0.0

Подробности примера использования

Определено в GHC.IO.Exception

Методы

showsPrec :: Int -> Deadlock -> ShowS Исходный код

show :: Deadlock -> Строка Исходный код

showList :: [Deadlock] -> ShowS Исходный код

Исключение Deadlock

С момента выпуска: base-4.1.0.0

Подробности примера использования

Определено в GHC.IO.Exception

Методы

toException :: Deadlock -> SomeException Исходный код

fromException :: SomeException -> Может быть Deadlock Исходный код

displayException :: Deadlock -> Строка Исходный код

newtype ОшибкаОтсутствияМетода Исходный код

Был вызван метод класса без определения (ни с определением по умолчанию, ни с определением в соответствующем примере). String содержит информацию о том, какой именно это был метод.

Конструкторы

ОшибкаОтсутствияМетода Строка
Примеры использования
Подробности примеров использования
Show ОшибкаОтсутствияМетода

С момента выпуска: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> ОшибкаОтсутствияМетода -> ShowS Исходный код

show :: ОшибкаОтсутствияМетода -> Строка Исходный код

showList :: [ОшибкаОтсутствияМетода] -> ShowS Исходный код

Исключение ОшибкаОтсутствияМетода

С момента выпуска: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

toException :: ОшибкаОтсутствияМетода -> SomeException Исходный код

fromException :: SomeException -> Может быть ОшибкаОтсутствияМетода Исходный код

displayException :: ОшибкаОтсутствияМетода -> Строка Исходный код

newtype ОшибкаНесоответствияШаблону Исходный код

Произошло несоответствие шаблона. String содержит информацию о расположении источника шаблона.

Конструкторы

ОшибкаНесоответствияШаблону Строка
Примеры использования
Подробности примеров использования
Show PatternMatchFail

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> PatternMatchFail -> ShowS Исходный код

show :: PatternMatchFail -> Строка Исходный код

showList :: [PatternMatchFail] -> ShowS Исходный код

Исключение PatternMatchFail

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

toException :: PatternMatchFail -> SomeException Исходный код

fromException :: SomeException -> Maybe PatternMatchFail Исходный код

displayException :: PatternMatchFail -> Строка Исходный код

newtype RecConError Исходный код

Использовалось неоинициализированное поле записи. String содержит информацию о расположении источника, где была создана запись.

Конструкторы

RecConError Строка
Примеры использования
Подробности примеров использования
Show RecConError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> RecConError -> ShowS Исходный код

show :: RecConError -> Строка Исходный код

showList :: [RecConError] -> ShowS Исходный код

Исключение RecConError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

toException :: RecConError -> SomeException Исходный код

fromException :: SomeException -> Maybe RecConError Исходный код

displayException :: RecConError -> Строка Исходный код

newtype RecSelError Исходный код

К селектору записи был применён конструктор без соответствующего поля. Это может произойти только с типом данных, имеющим несколько конструкторов, где некоторые поля есть в одном конструкторе, но отсутствуют в другом. String содержит информацию о расположении селектора записи.

Конструкторы

RecSelError Строка
Примеры использования
Подробности примеров использования
Show RecSelError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> RecSelError -> ShowS Исходный код

show :: RecSelError -> Строка Исходный код

showList :: [RecSelError] -> ShowS Исходный код

Исключение RecSelError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

toException :: RecSelError -> SomeException Исходный код

fromException :: SomeException -> Может быть RecSelError Исходный код

displayException :: RecSelError -> Строка Исходный код

newtype RecUpdError Исходный код

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

Конструкторы

RecUpdError Строка
Примеры использования
Подробности примеров использования
Show RecUpdError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

Методы

showsPrec :: Целое -> RecUpdError -> ShowS Исходный код

show :: RecUpdError -> Строка Исходный код

showList :: [RecUpdError] -> ShowS Исходный код

Исключение RecUpdError

С версии: base-4.0

Подробности примера использования

Определено в Control.Exception.Base

toException :: RecUpdError -> SomeException Исходный код

fromException :: SomeException -> Может быть RecUpdError Исходный код

displayException :: RecUpdError -> Строка Исходный код

data ErrorCall Исходный код

Это выбрасывается, когда пользователь вызывает error. Первое String — это аргумент, переданный error, а второе String — местоположение.

Конструкторы

ErrorCallWithLocation Строка Строка

Связанные шаблоны

pattern ErrorCall :: Строка -> ErrorCall
Примеры использования
Подробности примеров использования
Eq ErrorCall

С момента выпуска: base-4.7.0.0

Подробности примера использования

Определено в GHC.Exception

Методы

== :: ErrorCall -> ErrorCall -> Bool Исходный код

/= :: ErrorCall -> ErrorCall -> Bool Исходный код

Ord ErrorCall

С момента выпуска: base-4.7.0.0

Подробности примера использования

Определено в GHC.Exception

Методы

compare :: ErrorCall -> ErrorCall -> Ordering Исходный код

< :: ErrorCall -> ErrorCall -> Bool Исходный код

<= :: ErrorCall -> ErrorCall -> Bool Исходный код

> :: ErrorCall -> ErrorCall -> Bool Исходный код

>= :: ErrorCall -> ErrorCall -> Bool Исходный код

max :: ErrorCall -> ErrorCall -> ErrorCall Исходный код

min :: ErrorCall -> ErrorCall -> ErrorCall Исходный код

Show ErrorCall

С момента выпуска: base-4.0.0.0

Подробности примера использования

Определено в GHC.Exception

Методы

showsPrec :: Int -> ErrorCall -> ShowS Исходный код

show :: ErrorCall -> String Исходный код

showList :: [ErrorCall] -> ShowS Исходный код

Исключение ErrorCall

С момента выпуска: base-4.0.0.0

Подробности примера использования

Определено в GHC.Exception

Методы

toException :: ErrorCall -> SomeException Исходный код

fromException :: SomeException -> Maybe ErrorCall Исходный код

displayException :: ErrorCall -> String Исходный код

newtype ОшибкаТипизации Исходный код

Вызвана ошибка типизации во время компиляции. Это возможно только с помощью флага -fdefer-type-errors. String предоставляет подробности о несоответствии типов.

С момента выпуска: base-4.9.0.0

Конструкторы

ОшибкаТипизации Строка
Примеры использования
Подробности примеров
Show TypeError

С момента выпуска: base-4.9.0.0

Подробности примера

Определено в Control.Exception.Base

Методы

showsPrec :: Int -> TypeError -> ShowS Исходный код

show :: TypeError -> Строка Исходный код

showList :: [TypeError] -> ShowS Исходный код

Исключение TypeError

С момента выпуска: base-4.9.0.0

Подробности примера

Определено в Control.Exception.Base

Методы

toException :: TypeError -> SomeException Исходный код

fromException :: SomeException -> Возможно TypeError Исходный код

displayException :: TypeError -> Строка Исходный код

Выбрасывание исключений

throw :: forall (r :: Тип исполнения). forall (a :: TYPE r). forall e. Исключение e => e -> a Исходный код

Выбросить исключение. Исключения могут быть выброшены из чисто функционального кода, но могут быть перехвачены только в IO монаде.

throwIO :: Исключение e => e -> IO a Исходный код

Вариант throw, который может быть использован только в IO монаде.

Хотя throwIO имеет тип, являющийся экземпляром типа throw, эти две функции немного отличаются:

throw e   `seq` x  ===> throw e
throwIO e `seq` x  ===> x

Первый пример вызовет исключение e, а второй — нет. Фактически, throwIO вызовет исключение только при использовании в IO монаде. Вариант throwIO следует использовать вместо throw для выброса исключения в IO монаде, так как он гарантирует порядок с другими IO операциями, а throw — нет.

ioError :: ОшибкаIO -> IO a Исходный код

Выбросить IOError в IO монаде.

throwTo :: Исключение e => Идентификатор потока -> e -> IO () Исходный код

throwTo выбросит произвольное исключение в целевом потоке (только GHC).

Доставка исключений синхронизируется между исходным и целевым потоком: throwTo не вернется, пока исключение не будет выброшено в целевом потоке. Таким образом, вызывающий поток может быть уверен, что целевой поток получил исключение. Доставка исключений также атомарна по отношению к другим исключениям. Атомарность полезна при работе с гонками: например, если два потока могут убивать друг друга, гарантируется, что только один из потоков сможет убить другого.

Любая работа, которую выполнял целевой поток при выбросе исключения, не теряется: вычисление приостанавливается до тех пор, пока не потребуется другим потоком.

Если целевой поток в данный момент выполняет внешний вызов, то исключение не будет выброшено (и, следовательно, throwTo не вернётся) до завершения вызова. Это верно независимо от того, находится ли вызов внутри mask или нет. Однако в GHC внешний вызов может быть помечен как interruptible, в этом случае throwTo заставит RTS попытаться заставить вызов вернуть значение; см. документацию GHC для получения дополнительной информации.

Важно отметить: поведение throwTo отличается от описанного в статье "Асинхронные исключения в Haskell" (http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm). В статье throwTo неблокирующая, но библиотечная реализация использует более синхронный дизайн, в котором throwTo не возвращается, пока исключение не будет получено целевым потоком. Компромисс обсуждается в разделе 9 статьи. Как любая блокирующая операция, throwTo поэтому прерывимая (см. раздел 5.3 статьи). Однако в отличие от других прерывимых операций, throwTo всегда прерывимая, даже если она фактически не блокируется.

Нет гарантии, что исключение будет доставлено незамедлительно, хотя среда выполнения будет стремиться к тому, чтобы не возникало произвольных задержек. В GHC исключение может быть выброшено только тогда, когда поток достигает безопасной точки, где безопасная точка — это место, где происходит выделение памяти. Некоторые циклы не выполняют никакого выделения памяти внутри цикла и поэтому не могут быть прерваны throwTo.

Если целевой объект throwTo является вызывающим потоком, то поведение идентично throwIO, за исключением того, что исключение выброшено как асинхронное исключение. Это означает, что если есть окружающее чистое вычисление, что будет иметь место, если текущая операция IO находится внутри unsafePerformIO или unsafeInterleaveIO, это вычисление не заменяется исключением постоянно, а приостанавливается так, как если бы оно получило асинхронное исключение.

Обратите внимание, что если throwTo вызывается с текущим потоком в качестве целевого, исключение будет выброшено, даже если поток в данный момент находится внутри mask или uninterruptibleMask.

Перехват исключений

Существует несколько функций для перехвата и проверки исключений; все они могут быть использованы только изнутри IO монады.

Вот практическое правило для определения, какую функцию для перехвата использовать:

  • Если нужно выполнить некоторые действия по очистке в случае выброса исключения, используйте finally, bracket или onException.
  • Чтобы восстановиться после исключения и сделать что-то другое, лучше всего использовать одну из функций try.
  • ...если вы восстанавливаетесь после асинхронного исключения, используйте catch или catchJust.

Разница между использованием try и catch для восстановления заключается в том, что в catch обработчик находится внутри неявной mask (см. "Асинхронные исключения"), что важно при перехвате асинхронных исключений, но при перехвате других типов исключений это не нужно. Более того, возможно случайно остаться внутри неявной mask путем хвостового вызова, а не возвращения из обработчика, поэтому мы рекомендуем использовать try вместо catch для обычного восстановления от исключения.

Типичное использование tryJust для восстановления выглядит так:

 do r <- tryJust (guard . isDoesNotExistError) $ getEnv "HOME"
    case r of
      Left  e    -> ...
      Right home -> ...

Перехват всех исключений

Можно перехватить все исключения, используя тип SomeException:

catch f (\e -> ... (e :: SomeException) ...)

ОДНАКО, это обычно не то, что вы хотите сделать!

Например, предположим, что вы хотите прочитать файл, но если он не существует, то продолжить, как если бы он содержал "". Вы, возможно, захотите просто перехватить все исключения и вернуть "" в обработчике. Однако это имеет множество нежелательных последствий. Например, если пользователь нажмёт комбинацию клавиш Control-C в нужный момент, то исключение UserInterrupt будет перехвачено, и программа продолжит работу, полагая, что файл содержит "". Аналогично, если другая нить попытается убить нить, читающую файл, то исключение ThreadKilled будет проигнорировано.

Вместо этого вы должны перехватывать только те исключения, которые вам действительно нужны. В этом случае это, вероятно, будет более конкретно, чем даже "любое исключение IO"; ошибка доступа, скорее всего, также должна обрабатываться по-другому. Вместо этого вы, вероятно, захотите что-то вроде:

e <- tryJust (guard . isDoesNotExistError) (readFile f)
let str = either (const "") id e

Бывают случаи, когда вам действительно нужно перехватить любой вид исключения. Однако в большинстве случаев это необходимо только для того, чтобы выполнить некоторые очистительные операции; вас фактически не интересует само исключение. Например, если вы открываете файл, то хотите закрыть его снова, независимо от того, выполняется обработка файла нормально или возникает исключение. Однако в этих случаях вы можете использовать функции, такие как bracket, finally и onException, которые никогда фактически не передают вам исключение, а просто вызывают функции очистки в соответствующие моменты.

Но иногда вам действительно нужно перехватить любое исключение и фактически увидеть, что это за исключение. Один пример — в самом верхнем уровне программы, вы можете захотеть перехватить любое исключение, вывести его в лог-файл или на экран, а затем завершиться корректно. Для этих случаев вы можете использовать catch (или одну из других функций перехвата исключений) с типом SomeException.

Функции catch

catch Источник

Аргументы

:: Исключение e
=> IO a

Вычисляемый фрагмент кода

-> (e -> IO a)

Обработчик для вызова, если возникает исключение

-> IO a

Это самая простая из функций перехвата исключений. Она принимает один аргумент, выполняет его, и если возникает исключение, выполняется «обработчик», с значением исключения, переданным в качестве аргумента. В противном случае результат возвращается как обычно. Например:

  catch (readFile f)
        (\e -> do let err = show (e :: IOException)
                  hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err)
                  return "")

Обратите внимание, что мы должны указать тип для e, иначе программа не пройдёт типизацию, так как тип является неоднозначным. Хотя можно перехватывать исключения любого типа, см. раздел «Перехват всех исключений» (в Control.Exception) для объяснения проблем, связанных с этим.

Для перехвата исключений в чистых (не-IO) выражениях, см. функцию evaluate.

Обратите внимание, что из-за неопределённого порядка вычислений в Haskell выражение может выбросить одно из нескольких возможных исключений: рассмотрите выражение (error "urk") + (1 `div` 0). Выбрасывает ли выражение ErrorCall "urk", или DivideByZero?

Ответ — «может выбросить любое из них»; выбор не детерминирован. Если вы перехватываете любой тип исключения, то вы можете перехватить любое из них. Если вы вызываете catch с типом IO Int -> (ArithException -> IO Int) -> IO Int, то обработчик может быть вызван со значением DivideByZero в качестве аргумента или исключение ErrorCall "urk" может быть распространено дальше вверх. Если вы вызовете его снова, вы можете получить обратное поведение. Это нормально, так как catch — это IO вычисление.

catches :: IO a -> [Обработчик a] -> IO a Источник

Иногда вам нужно перехватить два разных типа исключений. Вы могли бы сделать что-то вроде

f = expr `catch` \ (ex :: ArithException) -> handleArith ex
         `catch` \ (ex :: IOException)    -> handleIO    ex

Однако есть несколько проблем с этим подходом. Во-первых, наличие двух обработчиков исключений неэффективно. Однако более серьёзная проблема заключается в том, что второй обработчик исключений перехватит исключения в первом, например, в приведённом выше примере, если handleArith сгенерирует исключение IOException, то второй обработчик исключений перехватит его.

Вместо этого мы предоставляем функцию catches, которая используется следующим образом:

f = expr `catches` [Handler (\ (ex :: ArithException) -> handleArith ex),
                    Handler (\ (ex :: IOException)    -> handleIO    ex)]

data Обработчик a Источник

Это необходимо при использовании catches.

Конструкторы

forall e.Исключение e => Обработчик (e -> IO a)
Примеры
Подробности примеров
Функтор Обработчик

С версии: base-4.6.0.0

Подробности примера

Определено в Control.Exception

Методы

fmap :: (a -> b) -> Обработчик a -> Обработчик b Источник

(<$) :: a -> Обработчик b -> Обработчик a Источник

catchJust Источник

Аргументы

:: Исключение e
=> (e -> Может быть b)

Предикат для выбора исключений

-> IO a

Вычисляемый фрагмент кода

-> (b -> IO a)

Обработчик

-> IO a

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

catchJust (\e -> if isDoesNotExistErrorType (ioeGetErrorType e) then Just () else Nothing)
          (readFile f)
          (\_ -> do hPutStrLn stderr ("No such file: " ++ show f)
                    return "")

Любые другие исключения, которые не соответствуют предикату, повторно генерируются и могут быть перехвачены вложенным catch, catchJust и т. д.

Функции handle

handle :: Исключение e => (e -> IO a) -> IO a -> IO a Источник

Вариант catch с переставленными аргументами; полезно в ситуациях, когда код обработчика короче. Например:

  do handle (\NonTermination -> exitWith (ExitFailure 1)) $
     ...

handleJust :: Исключение e => (e -> Может быть b) -> (b -> IO a) -> IO a -> IO a Источник

Вариант catchJust с переставленными аргументами (см. handle).

Функции try

try :: Исключение e => IO a -> IO (Either e a) Источник

Аналогично catch, но возвращает результат типа Either, который равен (Right a), если не было сгенерировано исключение типа e, или (Left ex), если было сгенерировано исключение типа e и его значение равно ex. Если возникает исключение другого типа, оно будет распространено к следующему вложенному обработчику исключений.

 try a = catch (Right `liftM` a) (return . Left)

tryJust :: Exception e => (e -> Maybe b) -> IO a -> IO (Either b a) Source

Вариант функции try, который принимает предикат исключения для выбора, какие исключения будут перехвачены (см. catchJust). Если исключение не соответствует предикату, оно повторно выбрасывается.

Функция evaluate

evaluate :: a -> IO a Source

Вычисляет аргумент до слабой нормальной формы головного уровня.

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

evaluate вычисляет только до слабой нормальной формы головного уровня. Если требуется более глубокое вычисление, функция force из Control.DeepSeq может быть полезной:

evaluate $ force x

Существует тонкое различие между evaluate x и return $! x, аналогичное различию между throwIO и throw. Если ленивое значение x вызывает исключение, return $! x не сможет вернуть действие IO и вместо этого выбросит исключение. evaluate x, с другой стороны, всегда создаёт действие IO; это действие выбросит исключение при выполнении тогда и только тогда, когда x выбросит исключение при вычислении.

Практическим следствием этого различия является то, что из-за семантики *неточных исключений*:

(return $! error "foo") >> error "bar"

может выбросить либо "foo", либо "bar", в зависимости от оптимизаций, выполненных компилятором. С другой стороны,

evaluate (error "foo") >> error "bar"

гарантированно выбросит "foo".

Правило заключается в том, чтобы использовать evaluate для принудительного вывода или обработки исключений в ленивых значениях. Если же вы принудительно выводите ленивое значение только для повышения эффективности и не беспокоитесь об исключениях, вы можете использовать return $! x.

Функция mapException

mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a Source

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

Асинхронные исключения

Асинхронные исключения возникают из-за внешних факторов и могут быть вызваны в любой момент выполнения. StackOverflow и HeapOverflow — два примера системных асинхронных исключений.

Однако основным источником асинхронных исключений является throwTo:

 throwTo :: ThreadId -> Exception -> IO ()

throwTo (также killThread) позволяет одному работающему потоку вызывать произвольное исключение в другом потоке. Таким образом, исключение является асинхронным по отношению к целевому потоку, который может заниматься чем угодно в момент получения исключения. С асинхронными исключениями следует обращаться с большой осторожностью; очень легко ввести гонки из-за чрезмерного использования throwTo.

Управление асинхронными исключениями

Следующие функции позволяют потоку управлять доставкой асинхронных исключений во время критической области.

mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b Source

Выполняет вычисление IO с *замаскированными* асинхронными исключениями. То есть любой поток, пытающийся вызвать исключение в текущем потоке с помощью throwTo будет заблокирован до тех пор, пока асинхронные исключения не будут снова размаскированы.

Аргумент, передаваемый в mask, — это функция, которая принимает в качестве аргумента другую функцию, которая может быть использована для восстановления текущего состояния маскировки в контексте вычисления с маской. Например, распространённый способ использования mask — защита приобретения ресурса:

mask $ \restore -> do
    x <- acquire
    restore (do_something_with x) `onException` release
    release

Этот код гарантирует, что acquire связано с release, замаскировав асинхронные исключения для критических участков. (Вместо того, чтобы писать этот код самостоятельно, лучше использовать bracket, который абстрагирует общий шаблон).

Обратите внимание, что действие restore, переданное в качестве аргумента mask, не обязательно размаскирует асинхронные исключения, оно только восстанавливает состояние маскировки до состояния окружающего контекста. Таким образом, если асинхронные исключения уже замаскированы, mask не может использоваться для размаскирования исключений снова. Это сделано для того, чтобы, если вы вызываете функцию библиотеки с замаскированными исключениями, вы могли быть уверены, что функция библиотеки не сможет размаскировать исключения. Если вы пишете код библиотеки и вам нужно использовать асинхронные исключения, единственный способ — создать новый поток; см. forkIOWithUnmask.

Асинхронные исключения всё ещё могут быть получены во время замаскированного состояния, если замаскированный поток *блокируется* определёнными способами; см. Control.Exception.

Потоки, созданные forkIO, наследуют состояние MaskingState от родителя; то есть, чтобы запустить поток в состоянии MaskedInterruptible, используйте mask_ $ forkIO .... Это особенно полезно, если вам нужно установить обработчик исключений в разветвлённом потоке до получения каких-либо асинхронных исключений. Чтобы создать новый поток в размаскированном состоянии, используйте forkIOWithUnmask.

mask_ :: IO a -> IO a Source

Аналогично mask, но не передаёт действие restore в аргумент.

uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b Source

Аналогично mask, но вычисление с маской не прерывается (см. Control.Exception). К ЭТОМУ СЛЕДУЕТ ОТНОСИТЬСЯ С БОЛЬШОЙ ОСТОРОЖНОСТЬЮ, потому что если поток, выполняющий вычисление с маской, заблокируется по какой-либо причине, то поток (и, возможно, программа, если это основной поток) станет нереагирующим и неубиваемым. Эта функция должна потребоваться только в том случае, если вам нужно замаскировать исключения вокруг прерываемого действия, и вы можете гарантировать, что прерываемое действие будет блокироваться только на короткий период времени.

uninterruptibleMask_ :: IO a -> IO a Source

Аналогично uninterruptibleMask, но не передаёт действие restore в аргумент.

data MaskingState Source

Описывает поведение потока при получении асинхронного исключения.

Конструкторы

Unmasked

асинхронные исключения не замаскированы (нормальное состояние)

MaskedInterruptible

состояние во время mask: асинхронные исключения замаскированы, но блокирующие операции всё ещё могут быть прерваны

MaskedUninterruptible

состояние во время uninterruptibleMask: асинхронные исключения замаскированы, и блокирующие операции не могут быть прерваны

Примеры
Подробности примеров
Eq MaskingState

С версии: base-4.3.0.0

Подробности примера

Определено в GHC.IO

Методы

(==) :: MaskingState -> MaskingState -> Bool Исходный код

(/=) :: MaskingState -> MaskingState -> Bool Исходный код

Show MaskingState

С версии: base-4.3.0.0

Подробности примера

Определено в GHC.IO

Методы

showsPrec :: Int -> MaskingState -> ShowS Исходный код

show :: MaskingState -> String Исходный код

showList :: [MaskingState] -> ShowS Исходный код

getMaskingState :: IO MaskingState Исходный код

Возвращает MaskingState для текущей нити.

interruptible :: IO a -> IO a Исходный код

Разрешает поднятие асинхронных исключений даже внутри mask, делая операцию прерываемой (см. обсуждение «Прерываемых операций» в Exception).

При вызове вне mask, или внутри uninterruptibleMask, эта функция не имеет эффекта.

С версии: base-4.9.0.0

allowInterrupt :: IO () Исходный код

При вызове внутри mask, эта функция разрешает поднятие замаскированного асинхронного исключения, если оно существует. Эквивалентно выполнению прерываемой операции (см. #interruptible), но не включает в себя реальное ожидание.

При вызове вне mask, или внутри uninterruptibleMask, эта функция не имеет эффекта.

С версии: base-4.4.0.0

Применение mask к обработчику исключений

Есть неявное mask вокруг каждого обработчика исключений в вызове одной из функций семейства catch. Это то, что нужно в большинстве случаев — это устраняет распространенную гонку при запуске обработчика исключений, потому что может не быть обработчика исключений в стеке для обработки другого исключения, если оно появится сразу. Однако, если асинхронные исключения замаскированы при входе в обработчик, у нас есть время для установки нового обработчика исключений перед прерыванием. Если бы это не было по умолчанию, пришлось бы написать что-то вроде

     mask $ \restore ->
          catch (restore (...))
                (\e -> handler)

Если вам нужно снова размаскировать асинхронные исключения в обработчике исключений, restore можно использовать там тоже.

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

Прерываемые операции

Некоторые операции являются прерываемыми, что означает, что они могут получать асинхронные исключения даже в рамках mask. Любая функция, которая может сама блокироваться, определяется как прерываемая; это включает takeMVar (но не tryTakeMVar), и большинство операций, которые выполняют некоторое ввод/вывод с внешним миром. Причина наличия прерываемых операций заключается в том, что мы можем написать такие вещи, как

     mask $ \restore -> do
        a <- takeMVar m
        catch (restore (...))
              (\e -> ...)

Если бы takeMVar не была прерываемой, то это конкретное сочетание могло привести к тупику, потому что нить сама была бы заблокирована в состоянии, в котором она не может получить какие-либо асинхронные исключения. Однако, с прерываемой takeMVar, мы можем быть уверены, что нить может получать исключения вплоть до момента, когда takeMVar завершается успешно. Аналогичные аргументы применяются для других прерываемых операций, таких как openFile.

Полезно рассматривать mask не как способ полностью предотвратить асинхронные исключения, а как способ переключения с асинхронного режима на режим опроса. Основная сложность с асинхронными исключениями заключается в том, что они обычно могут возникать где угодно, но в рамках mask асинхронное исключение поднимается только операциями, которые прерываемы (или вызывают другие прерываемые операции). Во многих случаях эти операции сами могут поднимать исключения, такие как ошибки ввода/вывода, поэтому вызывающая сторона обычно готова обработать исключения, возникающие из операции. Для выполнения явного опроса асинхронных исключений внутри mask, используйте allowInterrupt.

Иногда слишком сложно обрабатывать исключения в середине критической части состоявшего кода. Есть три способа справиться с этой ситуацией:

  • Используйте STM. Поскольку транзакция всегда полностью выполняется или вообще не выполняется, транзакции — хороший способ поддерживать инварианты состояния в присутствии асинхронных (и, действительно, синхронных) исключений.
  • Используйте mask, и избегайте прерываемых операций. Для этого нам нужно знать, какие операции прерываемы. Невозможно знать для любой функции библиотеки, может ли она вызвать прерываемую операцию внутри; поэтому вместо этого мы даем список операций, гарантированно не прерываемых ниже.
  • Используйте uninterruptibleMask. Это вообще не рекомендуется, если вы не можете гарантировать, что любые прерываемые операции, вызванные в рамках uninterruptibleMask, могут блокироваться только в течение короткого времени. В противном случае, uninterruptibleMask — хороший способ заставить вашу программу зависнуть и не реагировать на прерывания пользователя.

Следующие операции гарантированно не прерываемы:

  • операции над IORef из Data.IORef
  • STM-транзакции, которые не используют retry
  • всё из модулей Foreign
  • всё из Control.Exception за исключением throwTo
  • tryTakeMVar, tryPutMVar, isEmptyMVar
  • takeMVar если MVar определенно заполнен, и, наоборот, putMVar если MVar определенно пуст
  • newEmptyMVar, newMVar
  • forkIO, myThreadId

Утверждения

assert :: Bool -> a -> a Исходный код

Если первое аргумент вычисляется до True, то результатом является второй аргумент. В противном случае поднимается исключение AssertionFailed, содержащее String с именем исходного файла и номером строки вызова assert.

Утверждения обычно можно включать или выключать с помощью флага компилятора (для GHC, утверждения обычно включены, если оптимизация не включена с помощью -O или флаг -fignore-asserts задан). Когда утверждения отключены, первый аргумент для assert игнорируется, а в качестве результата возвращается второй аргумент.

Утилиты

bracket Исходный код

Аргументы

:: IO a

вычисление для первого выполнения («получение ресурса»)

-> (a -> IO b)

вычисление для последнего выполнения («освобождение ресурса»)

-> (a -> IO c)

вычисление для выполнения между ними

-> IO c

Когда вы хотите получить ресурс, выполнить с ним некоторую работу и затем освободить его, рекомендуется использовать bracket, так как bracket установит необходимый обработчик исключений для освобождения ресурса в случае возникновения исключения во время вычисления. Если возникнет исключение, то bracket повторно возбудит исключение (после выполнения освобождения).

Примеры часто встречаются при открытии файла:

bracket
  (openFile "filename" ReadMode)
  (hClose)
  (\fileHandle -> do { ... })

Аргументы для bracket расположены в таком порядке, чтобы мы могли частично применить его, например:

withFile name mode = bracket (openFile name mode) hClose

bracket_ :: IO a -> IO b -> IO c -> IO c Source

Вариант bracket, где возвращаемое значение от первого вычисления не требуется.

bracketOnError Source

Аргументы

:: IO a

вычисление, которое выполняется первым ("получить ресурс")

-> (a -> IO b)

вычисление, которое выполняется последним ("освободить ресурс")

-> (a -> IO c)

вычисление, которое выполняется между ними

-> IO c

Подобно bracket, но выполняет только конечное действие, если в промежуточном вычислении возникло исключение.

finally Source

Аргументы

:: IO a

вычисление, которое выполняется первым

-> IO b

вычисление, которое выполняется после (даже если возникло исключение)

-> IO a

Специализированный вариант bracket с только вычислением для выполнения после.

onException :: IO a -> IO b -> IO a Source

Подобно finally, но выполняет только конечное действие, если в вычислении возникло исключение.

© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/8.10.2/docs/html/libraries/base-4.14.1.0/Control-Exception.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API