目次
GHCは、ghcパッケージを通じてその内部APIを露出している。これを使うと、GHCのコンパイルドライバ全体を活用して、Haskellコードを分析したりコンパイルしたりするプログラムを書くことができる。またGHCは、コンパイル中にコンパイラプラグイン(GHCの内部中間表現Coreを見たり変更したりすることを許されたモジュール)をロードする能力を利用者に与える。プラグインは実験的な最適化や解析などに適しており、多くのよくある場合に関して、コンパイラの開発に参入する障壁を低くする。
加えて、GHCは軽量な注釈機構を用意しており、ソースコードにメタデータで注釈を付けて、後でコンパイラAPIまたはコンパイラプラグインを使って読み出すことができる。
注釈(annotation)とは、ソースコード中の識別子にデータを添付するための小さなプラグマである。添付したデータはコンパイル中残り続け、GHCをライブラリとして使ったり、コンパイラプラグインを書いたりする際に読んで利用することができる。
最上位の値の束縛には、ANN
プラグマを使って、Typeable
とData
の両方のインスタンスであるような任意の式を添付することができる。したがって、特に、通常の値(例えばtake
)だけでなくデータ構築子(例えばJust
)にもANN
を使って注釈を付けられる。例として、foo
という関数にJust "Hello"
を注釈として付けるには、次のようにする。
{-# ANN foo (Just "Hello") #-} foo = ...
注釈の利用には、いくつか制限が課せられる。
注釈を付ける束縛は最上位のものでなければならない(つまり、ネストしていてはならない)
注釈を付ける束縛は現在のモジュールで宣言されていなければならない
注釈とする式は、Typeable
とData
の両方のインスタンスのある型でなければならない。
注釈とする式にはTemplate Haskellの段階制約が課せられるので、例えばコンパイル中のモジュールの関数を走らせることはできない。
正確には、注釈{-# ANN x e #-}
が段階として正しい(well staged)のは、$(e)
が段階として正しい場合であり、その場合に限る。(ただし、接合構文にかかる通常の型の制限は無視し、接合の中に接合を書くことについての通常の制限も無視する。$([|1|])
は注釈として問題ない(冗長ではあるが)。)
これらの制限のうちどれかがあまりに重荷だと強く思うなら、GHCチームに連絡を寄越して欲しい。
一方で、これらの制限を別にすれば、多くのことが許されており、完全に評価されていない式でさえも使うことができる。注釈式は、Template Haskellの接合がコンパイラによって評価されるのとちょうど同じように評価される。よって、この注釈は問題ない。
{-# ANN f SillyAnnotation { foo = (id 10) + $([| 20 |]), bar = 'f } #-} f = ...
ANN
プラグマで型に注釈を付けるには、type
キーワードを使う。例を示す。
{-# ANN type Foo (Just "A `Maybe String' annotation") #-} data Foo = ...
ANN
プラグマでモジュールに注釈を付けるには、module
キーワードを使う。例を示す。
{-# ANN module (Just "A `Maybe String' annotation") #-}