昨日はGHCのコマンドの基本的な使い方を説明した。
今日からは、対話環境であるGHCiの使い方を中心に説明していく。
まずは、モジュールのロードについて。
モジュールのロード
とりあえず、次のような2つのHaskellのソースコードを用意してみる。
-- Main.hs import System.Environment import Control.Monad import Fibo main = do args <- getArgs when (length args > 0) $ do let count = read $ head args print $ map fibo [1..count]
-- Fibo.hs module Fibo (fibo) where fibo :: Integer -> Integer fibo n = fibo' n 1 1 fibo' :: Integer -> Integer -> Integer -> Integer fibo' 1 a b = a fibo' n a b = fibo' (n - 1) b (a + b)
これらをGHCiからロードしてみる。
ロードには:load
コマンド(省略形は:l
)を使う。
Prelude> :l Main [1 of 2] Compiling Fibo ( Fibo.hs, interpreted ) [2 of 2] Compiling Main ( Main.hs, interpreted ) Ok, modules loaded: Fibo, Main. *Main>
ロード対象として指定したのはMain.hsだけど、Fibo.hsとMain.hsの両方がコンパイルされ、ロードされている。
このように、ロード対象として指定されたモジュールからインポートされているモジュールも、一緒にロードされる。
ただし、よく見てみれば、System.EnvironmentやControl.MonadというモジュールもMain.hsからはインポートされているのに、Fibo.hsとは違ってロードされていないように見える。(実際にはロードされている)
どうしてこうなるのかというと、これらはパッケージに含まれているモジュールで、パッケージに含まれているモジュールは、必要になったら(例えば、後述のモジュールのインポートを行ったときなど)自動的にロードされるから。
なので、ロードされたことが明示的には表示されない。
あと、プロンプトが変化していることに気がつくと思う。
これは、
- Mainモジュールがインポートされている(※ロードではない)
- Mainモジュールがスコープ内にある(※アスタリスクのついている意味)
ことを意味している。(詳細はまた後日)
ちなみに、プログラムを走らせてみると、次のような感じ。
*Main> :main 20 [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765] *Main>
フィボナッチ数列が指定された数だけ表示される。
ロードされたモジュールの一覧
ロードされたモジュールの一覧を確認するには、:show modules
コマンドを使う。
*Main> :show modules Fibo ( Fibo.hs, interpreted ) Main ( Main.hs, interpreted ) *Main>
これは、
- Fiboというモジュールは、Fibo.hsというファイルがバイトコードとしてロードされ、インタプリタで実行される
- Mainというモジュールは、Main.hsというファイルがバイトコードとしてロードされ、インタプリタで実行される
ことを意味する。
(※Mainというモジュール名は、Main.hsというファイル名だからでなく、名前のついていないモジュールだからということに注意)
モジュールのリロード
:reload
コマンド(省略形は:r
)を使うと、ロードされているモジュールが必要に応じてリロードされる。
例えば、Fibo.hsのタイムスタンプを更新して、リロードしてみる。
*Main> :show modules Fibo ( Fibo.hs, interpreted ) Main ( Main.hs, interpreted ) *Main> :r Ok, modules loaded: Fibo, Main. *Main> :! touch Fibo.hs *Main> :r [1 of 2] Compiling Fibo ( Fibo.hs, interpreted ) Ok, modules loaded: Fibo, Main. *Main>
:!
コマンドを使うと任意のShellコマンドを実行できるので、touch
を使ってFibo.hsのタイムスタンプを更新している。
すると、何もしないでリロードした場合には何も起きていないのに、Fibo.hsのタイムスタンプを更新したあとでは、Fiboがリロードされていることが分かると思う。
ちなみに、ファイルを編集したい場合、:edit
コマンド(省略形は:e
)を使うといい。
EDITOR
環境変数で指定されたエディタが起動して、ファイルを編集することが出来る。
(ファイルの編集を終えると、GHCiへ戻ってくる)
モジュールのアンロード
あまりやる意味はないのだけど、モジュールをアンロードすることも出来る。
アンロードするには、引数を与えずに:load
コマンドを実行すればいい。
*Main> :show modules Fibo ( Fibo.hs, interpreted ) Main ( Main.hs, interpreted ) *Main> :l Ok, modules loaded: none. Prelude> :show modules Prelude>
見てのとおり、ロードされていたモジュールがすべてアンロードされる。
ちなみに、:cd
コマンドを使うとディレクトリを移動することが出来て、この場合もロードされていたすべてのモジュールはアンロードされる。
(ディレクトリが変わるので、検索パスが変わり、ソースコードを見つけることが出来なくなるから)
今日はここまで!