ソフトウェアの設計において、モジュールを相互参照させたい状況があります。論理的にはモジュールを細かく分ければ相互参照が起きないようにできる場合でも、意味的に考えた場合にそれらを分割したくないようなときです。
このエントリでは、GHCでHaskellのコードをコンパイルする際にモジュールを相互参照させる方法を紹介します。
The Haskell 98 Reportにおける記述
Haskellの言語仕様である"The Haskell 98 Report"では、モジュールは相互再帰をしても良いとされています。"5. Modules" in The Haskell 98 Report ... Modules may be mutually recursive. ...ところが、GHCでHaskellのコードをコンパイルする場合、そのままではモジュールを相互参照させることができずエラーとなります。
そうご参照させたモジュールをGHCでコンパイルする場合、追加の記述が少しだけ必要になります。
GHCで相互再帰モジュールをコンパイルするには
GHCは相互再帰モジュールをサポートしていますが、それをコンパイルするには、インポートグラフの循環参照回避のために、以下が必要となります。- SOURCEプラグマ
- hs-bootファイル
hs-bootファイルは、対応する.hsファイルのモジュール宣言や型宣言のみを抽出して記述したファイルです。.hs-boot拡張子を与えてプログラマが用意します。上述のSOURCEプラグマが付与されたモジュールをインポートする場合、インポートされる側のモジュールについては、.hsファイルではなく.hs-bootファイルから生成される情報を参照することになります。
具体的にどのように実装するかについては、GHCユーザガイドの4.7.9. How to compile mutually recursive moduleにて詳しく記述されています。
--