6.19.4. Assertions

If you want to make use of assertions in your standard Haskell code, you could define a function like the following:

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

which works, but gives you back a less than useful error message – an assertion failed, but which and where?

One way out is to define an extended assert function which also takes a descriptive string to include in the error message and perhaps combine this with the use of a pre-processor which inserts the source location where assert was used.

GHC offers a helping hand here, doing all of this for you. For every use of assert in the user’s source:

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

GHC will rewrite this to also include the source location where the assertion was made,

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

The rewrite is only performed by the compiler when it spots applications of Control.Exception.assert, so you can still define and use your own versions of assert, should you so wish. If not, import Control.Exception to make use assert in your code.

GHC ignores assertions when optimisation is turned on with the -O flag. That is, expressions of the form assert pred e will be rewritten to e. You can also disable assertions using the -fignore-asserts option. The option -fno-ignore-asserts allows enabling assertions even when optimisation is turned on.

Assertion failures can be caught, see the documentation for the Control.Exception library for the details.

6.19.5. The __GLASGOW_HASKELL_ASSERTS_IGNORED__ CPP macro

When code is compiled with assertions ignored (using -fignore-asserts or -O), the CPP macro __GLASGOW_HASKELL_ASSERTS_IGNORED__ will be defined. This can be used to conditionally compile your own custom assert-like functions. For example:

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