標準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)
上のようなものがあったとき、これを、アサーションが行われた地点を含むように書き換える。
assert pred val ==> assertError "Main.hs|15" pred val
このような書き換えが行われるのは、コンパイラがControl.Exception.assert
の適用を見つけたときだけである。したがって、もし望むなら、自分で定義したassert
を使うこともできる。そうでないなら、assert
を使うときはControl.Exception
をインポートせよ。
GHCは、-O
フラグで最適化が有効になっていると、アサーションを無視する。つまり、assert pred e
という形の式はe
に書き換えられる。-fignore-asserts
オプションを使ってアサーションを無効にすることもできる。-fno-ignore-asserts
オプションを使うと、最適化が有効な時でもアサーションを有効にしておくことができる。
アサーションの失敗は補足することができる。詳細はControl.Exception
の説明書きを見よ。