14.2. 既知のバグと問題点

バグトラッカには、報告されたもののまだ修正されていないGHCのバグが列挙されている。GHC Tracを見よ。加えて、GHCには、既知のバグや問題点として以下のものがある。これらはより永続的である。つまり、これらはどれも短期的に修正される可能性が低い。

14.2.1. GHCのバグ

  • GHCは、漏れのあるパターンや重複パターンについて警告することができる。(4.8. 警告と正気度チェックのためのオプションを見よ)。これは大抵の場合正しく動作するが、そうでないこともある。文字列パターンやガードがあると混乱し、不要な警告を出力することがある。本当は重複検査のコード全体を総点検する必要がある。

  • GHCは、データ型の文脈に、そのデータ型のパラメタ以外の型変数が出現することを許していない。例を挙げる。

    data C a b => T a = MkT a

    MkTの型は以下のようになるはずである。

    MkT :: forall a b. C a b => a -> T a

    原理的には、関数従属を使った適切なクラス宣言があれば、この型が曖昧でないこともあり得る。それでもGHCはこれを受け付けない。データ型宣言の文脈中に現れる型変数はそのデータ型の型パラメタのどれかでなければならない。

  • 再帰をデータ型にエンコードする標準的な方法を使うと、GHCのインライン化器を停止しないようにすることができる。

    data U = MkU (U -> Bool)
    
    russel :: U -> Bool
    russel u@(MkU p) = not $ p u
    
    x :: Bool
    x = russel (MkU russel)
    

    この不自然な例以外に、GHCを発散させるプログラムの形は見付かっていず、この問題を修正しようとするとあらゆるコンパイルにオーバーヘッドが掛かることになるので、このバグは修正されないままになっている。さらなる背景情報はSecrets of the GHC inlinerにある。

  • 32ビットのx86プラットフォームでネイティブコード生成器を使う場合、-fexcess-precisionオプションが常に有効になる。これにより、プログラムのコンパイルのされかた(例えば最適化設定)に依存して、ある種の浮動小数点演算が、32ビットや64ビットが意図されているにもかかわらず80ビットで為される。この結果、浮動小数点演算は非決定的になる。最適化が有効だと浮動小数点の結果が異なることがある。最悪の場合、参照透明性が守られない。let x = E1 in E2E2[E1/x]とは異なる値に評価され得るからである。

    回避策の一つに-msse2オプション(4.16. プラットフォーム固有のフラグ)を使うというものがある。これはx87命令セットの代わりにSSE2命令セットを使ってコードを生成する。SSE2は全ての浮動小数点演算を正しい精度で行なうので、決定的な結果を与える。ただし、これはSSE2に対応したプロセッサ(Intel Pentium 4またはAMD Athlon 64以降)においてのみ動作することに注意。このため、このオプションはデフォルトで有効になっていない。GHC付属のライブラリはおそらくこのオプションなしでビルドされている(あなたが自分でビルドしたのでないかぎり)。

14.2.2. GHCi(対話的GHC)のバグ

  • GHCiは、利用中のスコープのモジュールにあるdefault宣言を考慮せず、コマンド行に打ち込まれた式については、デフォルトのデフォルト化を行う。すなわち、default(Int,Double)である。

    GHCiがそれぞれのモジュールのデフォルト設定を覚えておいて、「現在の」モジュール(どういう意味かは別にして)のものを使うようにした方が良いだろう。

  • Windowsでは、GNU ld/BFDにバグがあり、0xffff個よりも多くの再配置のある、正しくないPEオブジェクトファイルを出力することがある。このバグに影響されたパッケージをGHCiがロードしようとすると、次のような形式のメッセージが得られる。

    Loading package javavm ... linking ... WARNING: Overflown relocation field (# relocs found: 30765)

    我々が最後に確認したときはこのバグはまだBFDのコードベースにあり、2001年あたりにこのバグが報告されて以来、興味がもたれた様子もない。

    回避するには、パッケージを構成する.oファイルを複数個の.oに分ければ良い。これは「base」パッケージが行っていることである。

  • 他のパッケージにあるインスタンス宣言に関して、どれが「スコープにあるか」をGHCは細かく管理しない。GHCが他のパッケージで見つけたインスタンス宣言はすべてプロンプトから利用可能であり、現在スコープにあるモジュールの集合を勘案した場合にそのインスタンスが可視であるべきかどうかに依らない。