2.2. ソースファイルをロードする

次のようなHaskellソースコードがMain.hsというファイルに置かれているとしよう。

main = print (fac 20)

fac 0 = 1
fac n = n * fac (n-1)

Main.hsはどこでも好きなところに保存することができるが、カレントディレクトリ[3]以外の場所に保存した場合、GHCiでディレクトリを正しく変更する必要がある。

Prelude> :cd dir

ここで、dirMain.hsを保存したディレクトリ(あるいはフォルダ)である。

HaskellのソースファイルをGHCiにロードするには、:loadコマンドを使う。

Prelude> :load Main
Compiling Main             ( Main.hs, interpreted )
Ok, modules loaded: Main.
*Main>

GHCiはMainモジュールをロードし、プロンプトが「*Main>」に変わった。これは、プロンプトに入力される式を評価するのに使われる文脈が、今ロードしたばかりのMainモジュールになったことを示すためのものである(*が何を意味するかについては2.4.5. プロンプトで実際にスコープにあるのは何かで説明する)。つまり、これでMain.hsで定義された関数を含む式を入力できるようになったということである。

*Main> fac 17
355687428096000

複数のモジュールからなるプログラムをロードするのも同様に簡単である。「最上位の」モジュールの名前を:loadコマンドに指定すれば良い(ヒント: :load:lに短縮できる)。最上位のモジュールはふつうMainであるが、必ずしもそうである必要はない。GHCiは最上位のモジュールから直接・間接に必要とされているモジュールを見付け、それらを依存関係の順にロードする。

2.2.1. モジュールとファイル名

GHCはMというモジュールがどのファイルにあるかをどのようにして知るのだろうか。GHCiは、M.hsまたはM.lhsというファイルを探すのである。したがって、大部分のモジュールでは、モジュール名とファイル名は一致しなければならない。一致しなかった場合、GHCiはモジュールを見つけ出すことができない。

この規則には一つの例外がある。:loadを使ってプログラムをロードするとき、あるいはghciを起動するとき、モジュール名ではなくファイル名を指定することができる。そのファイルはもし存在するならロードされ、どんなモジュールを含んでいても構わない。これは、複数のMainモジュールが一つのディレクトリにある場合、全てをMain.hsと呼ぶことはできないので、特に便利である。

ソースファイルを探すときの探索パスは、次に示すように、GHCiのコマンド行で-iを使って指定することができる。

ghci -idir1:...:dirn

あるいは、GHCiの中から:setコマンドを使って設定することもできる(2.8.2. GHCiからGHCのコマンド行オプションを設定するを見よ)[4]。

GHCiが上記のような方法で依存関係を追うことの帰結として、全てのモジュールにソースファイルがなければならない、というものがある。唯一の例外はパッケージ由来のモジュールで、これにはPreludeや、IOComplexといった標準ライブラリも含まれる。モジュールをロードしようとたときGHCiがソースファイルを見付けられなかった場合、たとえそのモジュールのオブジェクトファイルやインタフェースファイルがあったとしても、エラーメッセージが表示されるだろう。

2.2.2. ソースコードの変更と再コンパイル

ソースコードに変更を加えて、GHCiに再コンパイルさせたいときは、:reloadコマンドを使えば良い。プログラムは必要に応じて再コンパイルされる。このとき、GHCiは依存関係の変化がないモジュールを実際に再コンパイルするのを避けようと最善を尽くす。これは一括コンパイル時に再コンパイルを避ける機構(4.7.8. 再コンパイル検査器を見よ)と同じである。

[3]

GHCiをシェルから起動したのなら、GHCiのカレントディレクトリはシェルのそれと同じである。GHCiをWindowsの「スタート」メニューから起動したなら、カレントディレクトリはおそらくC:\Documents and Settings\user nameあたりになる。

[4]

GHCiや––makeモードでは-iオプションはソースファイルの探索パスを指定するのに対し、標準の一括コンパイルモードでは-iオプションはインターフェースファイルの探索パスを指定することに注意。4.7.3. 探索パスを見よ。