昨日はGHCiでのモジュールのロードについて説明した。
今日はGHCiでのモジュールのインポートについて説明する。
なお、Main.hsとFibo.hsについては、昨日の記事を参照。
モジュールのインポート
パッケージに含まれるモジュールをGHCiの中で使いたい場合、Haskellのコードを書くときと同様に、import
を使えばいい。
例えば、Data.Listをインポートしたければ、次のようにする。
Prelude> import Data.List Prelude Data.List>
プロンプトにData.Listが増えたけど、これはData.Listがインポートされていることを意味している。
モジュールのインポートを行えば、モジュールでエクスポートされている関数などを使うことが出来るようになる。
例えば、PerlやRubyのjoin
と同じような働きをするData.List.intercalate
を使ってみる。
Prelude Data.List> :l Main [1 of 2] Compiling Fibo ( Fibo.hs, interpreted ) [2 of 2] Compiling Main ( Main.hs, interpreted ) Ok, modules loaded: Fibo, Main. *Main Data.List> intercalate ", " $ map (show . fibo) [1..20] "1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765" *Main Data.List>
インポートされたモジュールの一覧
インポートされたモジュールの一覧を確認するには、:show imports
コマンドを使う。
*Main Data.List> :show imports import Data.List :module +*Main -- added automatically *Main Data.List>
見てみると、Data.Listがインポートされているのに追加して、Mainもインポートされていることが分かる。
これは、ロードを行ったときに自動的にインポートも行われるから。("added automatically"というのは、そういう意味)
:module
コマンドによるコントロール
:module
コマンド(省略形は:m
)を使うと、モジュールのインポートをコントロールすることが出来る。
まず、次のようにモジュール名に+
をつけると、モジュールをインポートすることが出来る。
*Main> :m +Data.List *Main Data.List> :show imports import Data.List :module +*Main -- added automatically *Main Data.List>
逆に、モジュール名に-
をつけると、モジュールのインポートを外すことが出来る。
*Main Data.List> :m -Data.List *Main> :show imports :module +*Main -- added automatically *Main>
あと、:module
コマンドを引数なしで実行した場合、すべてのモジュールのインポートが外される。
*Main> :m Prelude> :show imports import Prelude -- implicit Prelude>
ちなみに、上の状態ではモジュールは何もインポートされていないのだけど、Preludeという基本的なモジュールは暗黙的にインポートされていることになっている。(それが"implicit"の意味)
ところで、モジュールのインポートをすべて外したわけだけど、じゃあ、ロードされていたモジュールはどうなっているのか?
実は、モジュールのインポートを外しても、ロードされていたモジュールがアンロードもされてしまうというわけではない。
なので、次のようにすると、ロードされているモジュールがちゃんと表示される。
Prelude> :show modules Fibo ( Fibo.hs, interpreted ) Main ( Main.hs, interpreted ) Prelude>
ただし、インポートはされていないので、使うことは出来ない。
Prelude> :main 10 <interactive>:55:57: Not in scope: ‘main’ Perhaps you meant ‘min’ (imported from Prelude) Prelude>
main関数を見えるようにするために、Mainをインポートしてみる。
Prelude> :m Main Prelude Main>
こうすると、main関数を実行できるようになる。
Prelude Main> :main 20 [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765] Prelude Main>
けど、よく見ると、プロンプトが"*Main> "ではなく"Prelude Main> "となっている。
この違いは、fibo関数を実行してみると現れてくる。
*Main> fibo 20 6765 *Main>
Prelude Main> fibo 20 <interactive>:80:1: Not in scope: ‘fibo’ Prelude Main>
なんと、後者ではfibo関数が見つからない!
これがアスタリスクのついている意味で、アスタリスクがついている場合、そのモジュールがスコープ内に存在することになる。
どういうことかというと、Mainモジュールがスコープ内に存在している場合、Mainモジュールの中ではFiboモジュールもインポートされているので、Fiboモジュールでエクスポートされているfibo関数もスコープ内で見ることが出来る。
一方、Mainモジュールがスコープ内にない場合、スコープから見ることが出来るのはエクスポートされたMainモジュールの関数だけなので、Fiboモジュールでエクスポートされているfibo関数はスコープ内では見ることが出来ない。
つまり、簡単にいうと、次のようになっている。
モジュールをアスタリスクつきの状態でインポートするには、:module
コマンドでモジュール名に+*
をつければいい。
Prelude> :m +*Main *Main>
ちなみに、Fiboモジュールをアスタリスクつきでインポートすれば、エクスポートされていないfibo'関数を呼び出すことも出来る。
*Main> fibo' 10 1 1 <interactive>:86:1: Not in scope: ‘fibo'’ Perhaps you meant ‘fibo’ (imported from Fibo) *Main> :m +*Fibo *Main *Fibo> fibo' 10 1 1 55 *Main *Fibo>
今日はここまで!