Control.Exception
| Авторские права | (c) Университет Глазго 2001 |
|---|---|
| Лицензия | BSD-стиль (см. файл libraries/base/LICENSE) |
| Поддержка | libraries@haskell.org |
| Устойчивость | стабильная |
| Переносимость | непереносимая (расширенные исключения) |
| Безопасный Haskell | Надежный |
| Язык | Haskell2010 |
Описание
Этот модуль предоставляет поддержку для повышения и перехвата встроенных и пользовательских исключений.
В дополнение к исключениям, сгенерированным операциями IO, исключения могут быть сгенерированы чистым кодом (неточные исключения) или внешними событиями (асинхронные исключения), но могут быть перехвачены только в монаде IO. Для получения дополнительной информации см.:
- Семантика неточных исключений, Саймон Пейтон Джонс, Аластер Рид, Тони Хоар, Саймон Марлоу, Фергюс Хендерсон, в PLDI'99.
- Асинхронные исключения в Haskell, Саймон Марлоу, Саймон Пейтон Джонс, Энди Моран и Джон Реппи, в PLDI'01.
- Расширяемая динамически типизированная иерархия исключений, Саймон Марлоу, в Haskell '06.
Тип SomeException
data SomeException Исходный код
Тип SomeException является корнем иерархии типов исключений. Когда выбрасывается исключение типа e, за кулисами оно инкапсулируется в SomeException.
Конструкторы
| (Exception e, HasExceptionContext) => SomeException e |
Примеры
| Exception SomeException Исходный код |
Это отбрасывает любые присоединенные С версии: base-3.0 |
Определено в GHC.Internal.Exception.Type | |
| Show SomeException Исходный код | С версии: ghc-internal-3.0 |
Определено в GHC.Internal.Exception.Type МетодыshowsPrec :: Целое -> SomeException -> ShowS Исходный код show :: SomeException -> Строка Исходный код showList :: [SomeException] -> ShowS Исходный код | |
Класс Exception
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 Исходный код
toException должно создать SomeException без присоединенных ExceptionContext.
fromException :: SomeException -> Maybe e Исходный код
displayException :: e -> Строка Исходный код
Отобразить значение этого исключения в удобочитаемом виде.
Реализация по умолчанию: show.
С версии: base-4.8.0.0
backtraceDesired :: e -> Булево Исходный код
С версии: base-4.20.0.0
Примеры
| Исключение Таймаут Исходный код | С момента: base-4.7.0.0 |
Определено в System.Timeout | |
| Исключение Пустота Исходный код | С момента: base-4.8.0.0 |
Определено в GHC.Internal.Exception.Type | |
| Исключение ВложенноАтомарно Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Исключение НетСоответствияПрерывания Исходный код | С момента: base-4.18 |
Определено в GHC.Internal.Control.Exception.Base МетодыtoException :: НетСоответствияПрерывания -> НекотороеИсключение Исходный код fromException :: НекотороеИсключение -> Возможно НетСоответствияПрерывания Исходный код displayException :: НетСоответствияПрерывания -> Строка Исходный код backtraceDesired :: НетСоответствияПрерывания -> Булево Исходный код | |
| Исключение ОшибкаМетода Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Exception NonTermination Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Exception PatternMatchFail Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Exception RecConError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Exception RecSelError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Исключение RecUpdError Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Исключение TypeError Исходный код | С версии: base-4.9.0.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыtoException :: TypeError -> SomeException Исходный код fromException :: SomeException -> Может быть TypeError Исходный код | |
| Исключение Dynamic Исходный код | С версии: base-4.0.0.0 |
Определено в GHC.Internal.Data.Dynamic МетодыtoException :: Dynamic -> SomeException Исходный код fromException :: SomeException -> Может быть Dynamic Исходный код | |
| Исключение ErrorCall Исходный код | С версии: base-4.0.0.0 |
Определено в GHC.Internal.Exception | |
| Исключение ОшибкаАрифметики Исходныйкод | С: base-4.0.0.0 |
Определено в GHC.Internal.Exception.Type | |
| Исключение НекотораяОшибка Исходныйкод |
Это отбрасывает любые присоединённые С: base-3.0 |
Определено в GHC.Internal.Exception.Type | |
| Исключение ПревышенЛимитВыделения Исходныйкод | С: base-4.8.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Исключение ОшибкаМассива Исходныйкод | С: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Исключение Ошибка утверждения Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Исключение AsyncException Исходный код | С момента: base-4.7.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Исключение BlockedIndefinitelyOnMVar Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Исключение BlockedIndefinitelyOnSTM Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Exception CompactionFailed Исходный код | С момента: base-4.10.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Exception Deadlock Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыtoException :: Deadlock -> SomeException Исходный код fromException :: SomeException -> Maybe Deadlock Исходный код | |
| Exception ExitCode Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыtoException :: ExitCode -> SomeException Исходный код fromException :: SomeException -> Maybe ExitCode Исходный код | |
| Exception FixIOException Исходный код | С момента: base-4.11.0.0 |
Определено в GHC.Internal.IO.Exception МетодыtoException :: FixIOException -> SomeException Источник fromException :: SomeException -> Maybe FixIOException Источник | |
| Exception IOException Источник | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыtoException :: IOException -> SomeException Источник fromException :: SomeException -> Maybe IOException Источник | |
| Exception SomeAsyncException Источник | С момента: base-4.7.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Exception FileLockingNotSupported Источник | |
Определено в GHC.Internal.IO.Handle.Lock.Common | |
| Exception IOPortException Источник | |
Определено в GHC.Internal.IOPort МетодыtoException :: IOPortException -> SomeException Исходный код fromException :: SomeException -> Возможно IOPortException Исходный код displayException :: IOPortException -> Строка Исходный код backtraceDesired :: IOPortException -> Булево Исходный код | |
| Исключение a => Исключение (ИсключениеWithContext a) Исходный код | |
Определено в GHC.Internal.Exception.Type | |
| Исключение e => Исключение (БезТрейса e) Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыtoException :: БезТрейса e -> SomeException Исходный код fromException :: SomeException -> Возможно (БезТрейса e) Исходный код displayException :: БезТрейса e -> Строка Исходный код backtraceDesired :: БезТрейса e -> Булево Исходный код | |
addExceptionContext :: АннотацияИсключения a => a -> SomeException -> SomeException Исходный код
Добавить больше ExceptionContext к SomeException.
someExceptionContext :: SomeException -> КонтекстИсключения Исходный код
Просмотреть ExceptionContext SomeException.
annotateIO :: АннотацияИсключения e => e -> IO a -> IO a Исходный код
Выполнить действие IO, добавив заданную ExceptionContext к любым выброшенным синхронным исключениям.
С: base-2.20.0.0
newtype БезТрейса e Исходный код
Конструкторы
| БезТрейса e |
Примеры реализации
| Исключение e => Исключение (NoBacktrace e) Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыtoException :: NoBacktrace e -> SomeException Исходный код fromException :: SomeException -> Может быть (NoBacktrace e) Исходный код | |
| Show e => Show (NoBacktrace e) Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыshowsPrec :: Целое число -> NoBacktrace e -> ShowS Исходный код show :: NoBacktrace e -> Строка Исходный код showList :: [NoBacktrace e] -> ShowS Исходный код | |
data ExceptionWithContext a Исходный код
Оборачивает конкретное исключение, раскрывая его ExceptionContext. Предназначено для использования при catch исключений в тех случаях, когда требуется доступ к контексту.
Конструкторы
| ExceptionWithContext ExceptionContext a |
Примеры реализации
| Исключение a => Исключение (ExceptionWithContext a) Исходный код | |
Определено в GHC.Internal.Exception.Type | |
| Show a => Show (ExceptionWithContext a) Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыshowsPrec :: Целое число -> ExceptionWithContext a -> ShowS Исходный код show :: ExceptionWithContext a -> Строка Исходный код showList :: [ExceptionWithContext a] -> ShowS Исходный код | |
data WhileHandling Исходный код
WhileHandling используется для аннотирования перебрасываемых исключений. Просматривая WhileHandling аннотацию, можно восстановить все места, где исключение было переброшено.
Конструкторы
| WhileHandling SomeException |
Примеры использования
| ExceptionAnnotation WhileHandling Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыdisplayExceptionAnnotation :: WhileHandling -> Строка Исходный код | |
| Show WhileHandling Исходный код | |
Определено в GHC.Internal.Exception.Type МетодыshowsPrec :: Целое -> WhileHandling -> ShowS Исходный код show :: WhileHandling -> Строка Исходный код showList :: [WhileHandling] -> ShowS Исходный код | |
Конкретные типы исключений
data IOException Исходный код
Исключения, возникающие в IO монаде. IOException записывает более конкретный тип ошибки, описательную строку и, возможно, дескриптор, использованный при маркировании ошибки.
Примеры использования
| Исключение IOException Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Show IOException Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> IOException -> ShowS Исходный код show :: IOException -> Строка Исходный код showList :: [IOException] -> ShowS Исходный код | |
| Eq IOException Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception Методы(==) :: IOException -> IOException -> Булево Исходный код (/=) :: IOException -> IOException -> Булево Исходный код | |
data ArithException Исходный код
Арифметические исключения.
Конструкторы
| Overflow | |
| Underflow | |
| LossOfPrecision | |
| DivideByZero | |
| Denormal | |
| RatioZeroDenominator | С момента: base-4.6.0.0 |
Примеры
data ArrayException Исходный код
Исключения, сгенерированные операциями с массивами
Конструкторы
| IndexOutOfBounds Строка | Попытка индексировать массив за пределами объявленных границ. |
| UndefinedElement Строка | Попытка оценить элемент массива, который не был инициализирован. |
Примеры
newtype ОшибкаУтверждения Исходный код
assert было применено к False.
Конструкторы
| ОшибкаУтверждения Строка |
Примеры
| Исключение AssertionFailed Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Show AssertionFailed Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> AssertionFailed -> ShowS Исходный код show :: AssertionFailed -> Строка Исходный код showList :: [AssertionFailed] -> ShowS Исходный код | |
newtype NoMethodError Исходный код
Метод класса без определения (ни с дефолтным определением, ни с определением в соответствующем примере) был вызван. String содержит информацию о том, какой именно метод это был.
Конструкторы
| NoMethodError Строка |
Примеры
| Исключение NoMethodError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show NoMethodError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> NoMethodError -> ShowS Исходный код show :: NoMethodError -> Строка Исходный код showList :: [NoMethodError] -> ShowS Исходный код | |
newtype PatternMatchFail Исходный код
Сопоставление с образцом не удалось. String содержит информацию о местоположении источника шаблона.
Конструкторы
| PatternMatchFail Строка |
Примеры использования
| Исключение ОшибкаСопоставленияШаблонов Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыtoException :: ОшибкаСопоставленияШаблонов -> НекотороеИсключение Исходный код fromException :: НекотороеИсключение -> МожетБыть ОшибкаСопоставленияШаблонов Исходный код displayException :: ОшибкаСопоставленияШаблонов -> Строка Исходный код backtraceDesired :: ОшибкаСопоставленияШаблонов -> Булево Исходный код | |
| Show ОшибкаСопоставленияШаблонов Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> ОшибкаСопоставленияШаблонов -> ShowS Исходный код show :: ОшибкаСопоставленияШаблонов -> Строка Исходный код showList :: [ОшибкаСопоставленияШаблонов] -> ShowS Исходный код | |
newtype ОшибкаНеинициализированногоПоляЗаписи Исходный код
Было использовано неинициализированное поле записи. String содержит информацию о местоположении в исходном коде, где была создана запись.
Конструкторы
| ОшибкаНеинициализированногоПоляЗаписи Строка |
Примеры использования
newtype ОшибкаОбращенияКПолюЗаписи Исходный код
К селектору поля записи был применен конструктор без соответствующего поля. Это может произойти только с типом данных, имеющим несколько конструкторов, где некоторые поля присутствуют в одном конструкторе, но отсутствуют в другом. String содержит информацию о местоположении в исходном коде селектора поля записи.
Конструкторы
| ОшибкаОбращенияКПолюЗаписи Строка |
Примеры использования
| Исключение RecSelError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show RecSelError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> RecSelError -> ShowS Исходный код show :: RecSelError -> Строка Исходный код showList :: [RecSelError] -> ShowS Исходный код | |
newtype RecUpdError Исходный код
Обновление записи было выполнено для конструктора без соответствующего поля. Это может произойти только в случае типа данных с несколькими конструкторами, где некоторые поля присутствуют в одном конструкторе, но отсутствуют в другом. String содержит информацию о местоположении обновления записи.
Конструкторы
| RecUpdError Строка |
Примеры использования
| Исключение RecUpdError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show RecUpdError Исходный код | С момента: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> RecUpdError -> ShowS Исходный код show :: RecUpdError -> Строка Исходный код showList :: [RecUpdError] -> ShowS Исходный код | |
data ErrorCall Исходный код
Это выбрасывается, когда пользователь вызывает error. String — аргумент, переданный error.
Исторически существовал второй String для местоположения, но он был заменён механизмами отслеживания стека (с момента base-4.22).
Связанные шаблоны
| pattern ErrorCallWithLocation :: Строка -> Строка -> ErrorCall | Устаревший: ErrorCallWithLocation устарел в пользу ErrorCall (который не имеет местоположения). Теперь отслеживание стека обрабатывается исключительно механизмами исключений. |
Примеры
newtype ОшибкаТипизации Исходный код
Было вызвано выражение, которое не прошло проверку типов во время компиляции. Это возможно только с помощью -fdefer-type-errors. String предоставляет подробности о несоответствии проверки типов.
С момента: base-4.9.0.0
Конструкторы
| ОшибкаТипизации Строка |
Примеры
| Исключение ОшибкаТипа Исходный код | С момента: base-4.9.0.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show ОшибкаТипа Исходный код | С момента: base-4.9.0.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> ОшибкаТипа -> ShowS Исходный код show :: ОшибкаТипа -> Строка Исходный код showList :: [ОшибкаТипа] -> ShowS Исходный код | |
Асинхронные исключения
data НекоторыеАсинхронныеИсключения Исходный код
Базовый класс для асинхронных исключений.
С момента: base-4.7.0.0
Конструкторы
| Исключение e => НекоторыеАсинхронныеИсключения e |
Примеры
| Исключение НекоторыеАсинхронныеИсключения Исходный код | С момента: base-4.7.0.0 |
Определено в GHC.Internal.IO.Exception МетодыtoException :: НекоторыеАсинхронныеИсключения -> НекоторыеИсключения Исходный код fromException :: НекоторыеИсключения -> Возможно НекоторыеАсинхронныеИсключения Исходный код displayException :: НекоторыеАсинхронныеИсключения -> Строка Исходный код backtraceDesired :: НекоторыеАсинхронныеИсключения -> Булево Исходный код | |
| Show НекоторыеАсинхронныеИсключения Исходный код | С момента: base-4.7.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> НекоторыеАсинхронныеИсключения -> ShowS Исходный код show :: НекоторыеАсинхронныеИсключения -> Строка Исходный код showList :: [НекоторыеАсинхронныеИсключения] -> ShowS Исходный код | |
data АсинхронноеИсключение Исходный код
Асинхронные исключения.
Конструкторы
| StackOverflow | Превышен лимит стека текущей нити. Поскольку исключение было возбуждено, размер стека нити, безусловно, будет меньше лимита, но программист должен немедленно принять меры. |
| HeapOverflow |
Куча программы достигает своего лимита, и программе следует предпринять действия для уменьшения объема активных данных. Примечания:
|
| ThreadKilled | Это исключение возбуждается другой нитью, вызывающей |
| UserInterrupt | Это исключение по умолчанию возбуждается в основной нити программы, когда пользователь запрашивает завершение программы с помощью стандартного механизма (например, нажатия Control-C в консоли). |
Примеры
asyncExceptionToException :: Исключение e => e -> SomeException Исходный код
С тех пор как: base-4.7.0.0
asyncExceptionFromException :: Исключение e => SomeException -> Может быть e Исходный код
С тех пор как: base-4.7.0.0
Выбрасывается, когда система выполнения обнаруживает, что вычисление гарантированно не завершится. Обратите внимание, что нет гарантии, что система выполнения заметит, является ли данное вычисление гарантированно завершаемым или нет.
Конструкторы
| NonTermination |
Примеры реализации
| Исключение NonTermination Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show NonTermination Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> NonTermination -> ShowS Исходный код show :: NonTermination -> Строка Исходный код showList :: [NonTermination] -> ShowS Исходный код | |
data NestedAtomically Исходный код
Выбрасывается, когда программа пытается вызвать atomically, из пакета stm, внутри другого вызова atomically.
Конструкторы
| NestedAtomically |
Примеры реализации
| Исключение NestedAtomically Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base | |
| Show NestedAtomically Исходный код | С версии: base-4.0 |
Определено в GHC.Internal.Control.Exception.Base МетодыshowsPrec :: Целое -> NestedAtomically -> ShowS Исходный код show :: NestedAtomically -> Строка Исходный код showList :: [NestedAtomically] -> ShowS Исходный код | |
data BlockedIndefinitelyOnMVar Исходный код
Поток заблокирован на MVar, но других ссылок на MVar нет, поэтому он никогда не сможет продолжить работу.
Конструкторы
| BlockedIndefinitelyOnMVar |
Примеры реализации
| Исключение BlockedIndefinitelyOnMVar Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Вывод BlockedIndefinitelyOnMVar Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое число -> BlockedIndefinitelyOnMVar -> ShowS Исходный код show :: BlockedIndefinitelyOnMVar -> Строка Исходный код showList :: [BlockedIndefinitelyOnMVar] -> ShowS Исходный код | |
data BlockedIndefinitelyOnSTM Исходный код
Поток ожидает повторной попытки транзакции STM, но других ссылок на любые TVar нет, поэтому он никогда не сможет продолжить.
Конструкторы
| BlockedIndefinitelyOnSTM |
Примеры реализации
| Исключение BlockedIndefinitelyOnSTM Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Вывод BlockedIndefinitelyOnSTM Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое число -> BlockedIndefinitelyOnSTM -> ShowS Исходный код show :: BlockedIndefinitelyOnSTM -> Строка Исходный код showList :: [BlockedIndefinitelyOnSTM] -> ShowS Исходный код | |
data AllocationLimitExceeded Исходный код
Этот поток превысил лимит выделения. См. setAllocationCounter и enableAllocationLimit.
С момента: base-4.8.0.0
Конструкторы
| AllocationLimitExceeded |
Примеры
| Исключение AllocationLimitExceeded Исходный код | С момента: base-4.8.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Show AllocationLimitExceeded Исходный код | С момента: base-4.7.1.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> AllocationLimitExceeded -> ShowS Исходный код | |
newtype CompactionFailed Исходный код
Компактизация обнаружила объект, который нельзя сжать. Функции, мутабельные объекты или прикрепленные объекты сжать нельзя. См. compact.
С момента: base-4.10.0.0
Конструкторы
| CompactionFailed Строка |
Примеры
| Исключение CompactionFailed Исходный код | С момента: base-4.10.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Show CompactionFailed Исходный код | С момента: base-4.10.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> CompactionFailed -> ShowS Исходный код show :: CompactionFailed -> Строка Исходный код showList :: [CompactionFailed] -> ShowS Исходный код | |
data Deadlock Исходный код
Нет ни одного выполняемого потока, поэтому программа заблокирована. Исключение Deadlock возникает только в главном потоке.
Конструкторы
| Deadlock |
Примеры использования
| Исключение Зависание Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception | |
| Show Зависание Исходный код | С момента: base-4.1.0.0 |
Определено в GHC.Internal.IO.Exception МетодыshowsPrec :: Целое -> Зависание -> ShowS Исходный код show :: Зависание -> Строка Исходный код showList :: [Зависание] -> ShowS Исходный код | |
Выбрасывание исключений
throw :: forall a e. (HasCallStack, Исключение e) => e -> a Исходный код
Выбросить исключение. Исключения могут быть выброшены из чисто функционального кода, но могут быть перехвачены только внутри IO монады.
ПРЕДУПРЕЖДЕНИЕ: Возможно, вам следует использовать throwIO вместо этого, чтобы ваш чистый код оставался без исключений.
throwIO :: (HasCallStack, Исключение e) => e -> IO a Исходный код
Вариант throw, который может быть использован только внутри IO монады.
Несмотря на то, что throwIO имеет тип, являющийся экземпляром типа throw, эти две функции немного различаются:
throw e `seq` () ===> throw e throwIO e `seq` () ===> ()
В первом примере будет вызвано исключение e, а во втором — нет. Фактически, throwIO будет вызывать исключение только при использовании внутри IO монады.
Следует использовать вариант throwIO вместо throw для выброса исключения внутри IO монады, так как он гарантирует порядок относительно других операций, в то время как throw не гарантирует этого. Мы говорим, что throwIO выбрасывает *точные* исключения, а throw, error и т.д. выбрасывают *неточные* исключения. Например:
throw e + error "boom" ===> error "boom" throw e + error "boom" ===> throw e
оба являются допустимыми вычислениями, и компилятор может выбрать любое (включая цикл), в то время как
throwIO e >> error "boom" ===> throwIO e
всегда выбросит e при выполнении.
См. также страницу вики GHC о точных исключениях для более технического введения в то, как GHC оптимизирует точные и неточные исключения.
rethrowIO :: Исключение e => ИсключениеСКонтекстом e -> IO a Исходный код
Утилита для повторного выброса исключений. При повторном выбросе исключения новый стек вызовов не будет добавлен, но вы должны предоставить существующий контекст.
ioError :: HasCallStack => IOОшибка -> IO a Исходный код
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, вызывая функцию рекурсивно (tail-call) вместо возврата из обработчика, поэтому мы рекомендуем использовать try вместо catch для обычного восстановления после исключения.
Типичное использование tryJust для восстановления выглядит следующим образом:
do r <- tryJust (guard . isDoesNotExistError) $ getEnv "HOME"
case r of
Left e -> ...
Right home -> ...
Возможно перехватить все исключения, используя тип SomeException:
catch f (\e -> ... (e :: SomeException) ...)
ОДНАКО, это обычно не то, что нужно!
Например, предположим, что вы хотите прочитать файл, но если он не существует, то продолжить, как если бы он содержал "". Вы можете быть искушены просто перехватить все исключения и вернуть "" в обработчике. Однако это имеет много нежелательных последствий. Например, если пользователь нажмёт Ctrl+C в подходящий момент, исключение UserInterrupt будет перехвачено, и программа продолжит работу, полагая, что файл содержит "". Аналогично, если другая нить попытается убить нить, читающую файл, то исключение ThreadKilled будет проигнорировано.
Вместо этого вы должны перехватывать только те исключения, которые вам действительно нужны. В данном случае это, вероятно, будет более конкретно, чем даже «любое исключение ввода-вывода»; ошибку доступа, скорее всего, нужно обрабатывать по-другому. Вероятно, вы захотите что-то вроде:
e <- tryJust (guard . isDoesNotExistError) (readFile f) let str = either (const "") id e
Иногда вам действительно нужно перехватить любой тип исключения. Однако в большинстве случаев это делается только для того, чтобы выполнить некоторую очистку; вас не интересует само исключение. Например, если вы открываете файл, то вы хотите его закрыть, независимо от того, выполняется обработка файла нормально или возникает исключение. В таких случаях вы можете использовать функции, такие как bracket, finally и onException, которые никогда не передают вам исключение, а просто вызывают функции очистки в соответствующие моменты.
Но иногда вам действительно нужно перехватить любое исключение и увидеть, что это за исключение. Один пример — на самом верхнем уровне программы, вы можете захотеть перехватить любое исключение, вывести его в файл журнала или на экран, а затем выйти корректно. В таких случаях вы можете использовать catch (или одну из других функций перехвата исключений) с типом SomeException.
Аргументы
| :: Exception 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 вычисление.
catchNoPropagate :: Exception e => IO a -> (ExceptionWithContext e -> IO a) -> IO a Source
Вариант catch, который не аннотирует обработчик исключением, которое было перехвачено. Эта функция должна использоваться, когда вы реализуете свои собственные функции обработки ошибок, которые могут повторно генерировать исключения.
В случае, если вы повторно генерируете исключение без его изменения, вы должны повторно сгенерировать исключение со старым контекстом исключения.
catches :: IO a -> [Handler a] -> IO a Source
Иногда вы хотите перехватить два разных типа исключений. Вы можете сделать что-то вроде:
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)]
Вам это нужно при использовании catches.
Примеры реализации
Функция 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 :: Exception e => (e -> IO a) -> IO a -> IO a Источник
Вариант функции catch с переставленными аргументами; полезен в ситуациях, когда код обработчика короче. Например:
do handle (\NonTermination -> exitWith (ExitFailure 1)) $
...
handleJust :: Exception e => (e -> Maybe b) -> (b -> IO a) -> IO a -> IO a Источник
Вариант функции catchJust с переставленными аргументами (см. handle).
Функции try
try :: Exception e => IO a -> IO (Either e a) Источник
Аналогично catch, но возвращает результат типа Either, который является (Right a), если не было поднято исключение типа e, или (Left ex), если исключение типа e было поднято и его значение равно ex. Если поднят любой другой тип исключения, он будет передан вверх следующему обработчику исключений.
try a = catch (Right `liftM` a) (return . Left)
tryWithContext :: Exception e => IO a -> IO (Either (ExceptionWithContext e) a) Источник
Подобно try, но также возвращает контекст исключения, что полезно, если вы планируете повторно поднять исключение позже.
tryJust :: Exception e => (e -> Maybe b) -> IO a -> IO (Either b a) Источник
Вариант try, который использует предикат исключения для выбора исключений (см. catchJust). Если исключение не соответствует предикату, оно повторно выбрасывается.
Функция evaluate
evaluate :: a -> IO a Источник
Вычисляет аргумент до слабой головной нормальной формы.
Функция 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 Источник
Эта функция отображает одно исключение в другое, как предложено в статье "Семантика неточных исключений".
Асинхронные исключения
Асинхронные исключения так называются потому, что они возникают из-за внешних воздействий и могут быть подняты в любой момент выполнения. StackOverflow и HeapOverflow являются двумя примерами системных асинхронных исключений.
Однако основным источником асинхронных исключений является throwTo:
throwTo :: ThreadId -> Exception -> IO ()
throwTo (также killThread) позволяет одному выполняющемуся потоку поднимать произвольное исключение в другом потоке. Поэтому исключение является асинхронным относительно целевого потока, который в этот момент может выполнять любые действия. Следует проявлять большую осторожность при работе с асинхронными исключениями; очень легко ввести гонки при чрезмерном использовании throwTo.
mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b Источник
Выполняет вычисление 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 Источник
Подобно mask, но не передаёт действие restore в аргумент.
uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b Источник
Подобно mask, но замаскированное вычисление не прерывается (см. Control.Exception). ЭТО НУЖНО ИСПОЛЬЗОВАТЬ С ОСОБОЙ ОСТОРОЖНОСТЬЮ, поскольку если поток, выполняющийся в uninterruptibleMask, блокируется по любой причине, то поток (и, возможно, программа, если это основной поток) станет невосприимчивым к прерываниям и не убиваемым. Эта функция должна использоваться только в том случае, если вам нужно замаскировать исключения вокруг прерывимой операции, и вы можете гарантировать, что прерывимая операция будет блокироваться только на короткий период времени.
uninterruptibleMask_ :: IO a -> IO a Source
Подобно uninterruptibleMask, но не передает restore действие аргументу.
data MaskingState Source
Описывает поведение потока при получении асинхронного исключения.
Конструкторы
| Unmasked | асинхронные исключения не замаскированы (обычное состояние) |
| MaskedInterruptible | состояние во время |
| MaskedUninterruptible | состояние во время |
Экземпляры
| Show MaskingState Source | С момента: base-4.3.0.0 |
Определено в GHC.Internal.IO МетодыshowsPrec :: Int -> MaskingState -> ShowS Source show :: MaskingState -> String Source showList :: [MaskingState] -> ShowS Source | |
| Eq MaskingState Source | С момента: base-4.3.0.0 |
Определено в GHC.Internal.IO Методы(==) :: MaskingState -> MaskingState -> Bool Source (/=) :: MaskingState -> MaskingState -> Bool Source | |
getMaskingState :: IO MaskingState Source
Возвращает MaskingState для текущего потока.
interruptible :: IO a -> IO a Source
Разрешает возбуждение асинхронных исключений даже внутри mask, делая операцию прерывимой (см. обсуждение "прерывимых операций" в Exception).
Когда вызывается вне mask, или внутри uninterruptibleMask, эта функция не оказывает влияния.
С момента: base-4.9.0.0
allowInterrupt :: IO () Source
При вызове внутри 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 Source
Если первый аргумент вычисляется до True, то результатом является второй аргумент. В противном случае генерируется исключение AssertionFailed, содержащее String с именем файла и номером строки вызова assert.
Обычно утверждения можно включать или отключать с помощью флага компилятора (для GHC утверждения обычно включены, если оптимизация не включена с помощью -O или флага -fignore-asserts). Когда утверждения отключены, первый аргумент к assert игнорируется, и в качестве результата возвращается второй аргумент.
Утилиты
Аргументы
| :: 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 оборачивает действие освобождения с помощью mask, чего достаточно, чтобы гарантировать, что действие освобождения выполнится до конца, когда оно не вызывает какие-либо прерываемые действия, даже при наличии асинхронных исключений. Например, hClose не прерывается, когда оно не конкурирует с другими операциями с дескриптором. Точно так же закрытие сокета (из пакета «network») тоже не прерывается в аналогичных условиях. Примером прерываемого действия является killThread. Выполнение прерываемых действий по освобождению можно гарантировать, обернув их в uninterruptibleMask_, но это может сделать программу невосприимчивой к Control-C, или таймаутам. Другой вариант — запустить действие освобождения асинхронно в отдельном потоке:
void $ uninterruptibleMask_ $ forkIO $ do { ... }
Ресурс будет освобождён как можно скорее, но поток, вызвавший bracket, не будет заблокирован в непрорывемом состоянии.
bracket_ :: IO a -> IO b -> IO c -> IO c Source
Вариант bracket, где возвращаемое значение от первого вычисления не требуется.
Аргументы
| :: IO a | вычисление, которое выполняется первым ("получение ресурса") |
| -> (a -> IO b) | вычисление, которое выполняется последним ("освобождение ресурса") |
| -> (a -> IO c) | вычисление, которое выполняется между ними |
| -> IO c |
Как bracket, но выполняет последнее действие только в случае возникновения исключения в промежуточном вычислении.
Аргументы
| :: 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/9.12.1/docs/libraries/base-4.21.0.0-8e62/Control-Exception.html