Spec-Zone.ru › Haskell 9

6.19.4. Утверждения

Если вы хотите использовать утверждения в стандартном коде Haskell, можно определить функцию, подобную следующей:

assert :: Bool -> a -> a
assert False x = error "assertion failed!"
assert _     x = x

Она работает, но возвращает малополезное сообщение об ошибке: утверждение не выполнено, но какое именно и где?

Один из способов решить эту проблему — определить расширенную функцию assert, которая также принимает описательную строку для включения в сообщение об ошибке, и, возможно, объединить это с использованием препроцессора, вставляющего расположение в исходном коде, где использовалось assert.

GHC помогает решить эту задачу, выполняя всё это за вас. Для каждого использования assert в исходном коде пользователя:

kelvinToC :: Double -> Double
kelvinToC k = assert (k >= 0.0) (k-273.15)

GHC перепишет это выражение, добавив расположение в исходном коде, где было сделано утверждение,

assert pred val ==> assertError "Main.hs|15" pred val

Переписывание выполняется компилятором только при обнаружении вызовов Control.Exception.assert, поэтому при желании вы по-прежнему можете определять и использовать собственные версии assert. Если это не так, импортируйте Control.Exception, чтобы использовать assert в коде.

GHC игнорирует утверждения, когда включена оптимизация с флагом -O. То есть выражения вида assert pred e будут переписаны в e. Также можно отключить утверждения с помощью параметра -fignore-asserts. Параметр -fno-ignore-asserts позволяет включить утверждения, даже когда включена оптимизация.

Сбои утверждений можно перехватывать; подробности см. в документации библиотеки Control.Exception.

6.19.5. Макрос CPP __GLASGOW_HASKELL_ASSERTS_IGNORED__

Когда код компилируется с игнорированием утверждений (с использованием -fignore-asserts или -O), будет определён макрос CPP __GLASGOW_HASKELL_ASSERTS_IGNORED__. Его можно использовать для условной компиляции собственных функций, подобных assert. Например:

checkedAdd :: Word -> Word -> Word
#ifdef __GLASGOW_HASKELL_ASSERTS_IGNORED__
  checkedAdd lhs rhs = lhs + rhs
#else
  checkedAdd lhs rhs
    | res < lhs || res < rhs = raise OverflowException
    | otherwise              = res
    where res = lhs + rhs
#endif

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.14.1/docs/users_guide/exts/assert.html

Spec-Zone.ru

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