アサート
普通のHaskellコード内でアサートを使いたいときに,以下のような関数を定義することもまあできる.
code:assert1.hs
assert :: Bool -> a -> a
assert False x = error "assertion failed!"
assert _ x = x
これは動くが,返ってくるのは使い物にならないエラーメッセージである.「アサートが失敗した」…どのどこのアサート?
これを回避する方法の一つとして,説明の文字列も受け取ってエラーメッセージに含めてくれる,拡張されたassert関数を定義し,ことによるとそれにプリプロセッサを組み合わせてassertが使われたソースコード上の位置情報を挿入してくれるようにする,というのがある.
この状況においてGHCは救いの手を差し伸べてくれていて,これらすべてを代わりにやってくれる.ユーザーのソース内でassertが使われる毎に,
code:assert2.hs
kelvinToC :: Double -> Double
kelvinToC k = assert (k >= 0.0) (k-273.15)
GHCはこれを上書きしてアサートがなされたソース上の場所をも含むようにする.
code:assert3.hs
assert pred val ==> assertError "Main.hs|15" pred val
この上書きがなされるのは,コンパイラが Control.Exception.assertの関数適用を見つけたときのみであるので,万が一自分でassertを定義して使いたい場合はそうすることもできる.そうでなければ,コード内でassertを使うためには Control.Exception をインポートしよう.
最適化が-Oフラグでオンになっているときは,GHCはアサートを無視する.つまり, assert pred eの形の式はeへと上書きされる. -fignore-asserts オプションを使ってもアサートを無効にできる. -fno-ignore-assertsオプションを使うと,最適化がオンになっているときでもアサートを有効にできる.