突然main関数なんて出したけど、これの必要性について説明しよう。
今までは、関数を適当に定義して、対話式インタプリタで呼び出していた。
でも、独立した実行形式のファイルを作った場合はどうだろう?
windowsなどのOSは役所仕事なので、haskellのコードが持つ関数を理解してくれない。
だから、こちらから何を評価すれば良いか教えなくてはいけない。
そのための関数がmainなんだ。実行形式にすると、まずmain関数が呼び出される。
それじゃあ、main関数を持つソースコードを作ってみよう。
ちなみに、main関数は基本の関数なので、これを利用するだけのコードならモジュールの指定は要らない。
勝手にMainというモジュールだと解釈してくれるんだ。
それと、mainを用いたソースは、名前をmainにすると意味が分からないから、適当に名前を付けてね。
ここではhello.hsにするよ。
main = [[print]] "Hello, world!"
とりあえずコンパイルして実行形式を作ってみよう。
ここでは、コンソールを行き来するのが面倒なので、GHCiから呼び出すね。
:!コマンドを使うと、システムのコンソールコマンドを使えるんだ。
Prelude> :!ghc -o hello hello.hs
hello.exeのような実行形式が出来たかな? サイズは結構大きいね(汗
まあ、実行してみよう。
Prelude> :!hello
"Hello, world!"
うん、問題ないね。
さて、このプログラムは1文だけだから良いけど、もっと複雑なプログラムはどうしよう?
関数の定義は基本的に1文だから、これじゃあ作れないぞ?
ということは当然なくて、こういう風に書けばいいらしい。
main = do print "Hello, World!"
print "Welcome to haskell!"
printの頭は揃ってないといけないよ。そういう失敗は良くやるから、ちょっと動かしてエラー文を確認しておこう。
doについての情報はGHCiでは見つからない。後で調べてみよう。
ともあれ、これをコンパイルして実行するとこうなる。
*Prelude> :!ghc -o hello print.hs
*Prelude> :!hello
"Hello, World!"
"Welcome to haskell!"
doを使うと、命令文のようになるね。
これでmainが2行以上になるプログラムを作れるようになった。
他の言語では普通だけど、関数型言語は喜ぶところね。
今度はGHCiに戻って、型を分析しよう。
と、ここで関数を一つ紹介。他のサイトでは最初にでてくると思うけど、
Prelude> putStrLn "banana"
banana
putStrLnは文字列の内容を表示するんだ。
printに比べて大文字を使ってたり複雑っぽいから、説明を後回しにしてた。
これも使って、次のモジュールを作ろう。
module Test3 where
f1 = print "Hahaha!"
f2 = do print "Hehehe!"
f3 = do putStrLn "Hohoho!"
print 1023
g1 m1 m2 = do putStrLn m1
putStrLn m2
g2 a b = do print a
print b
実行結果は大体予想通りなので省略するよ。型を見てみよう。
*Test3> :t f1
f1 :: IO ()
*Test3> :t f2
f2 :: IO ()
*Test3> :t f3
f3 :: IO ()
*Test3> :t g1
g1 :: String -> String -> IO ()
*Test3> :t g2
g2 :: (Show a1, Show a) => a -> a1 -> IO ()
printの返り値がIO ()で、他の書き方をしてもIO ()になるようだね。
引数は関係ないようだ。
mainは、このように返り値がIO aになる関数じゃないといけないんだ。
試しに、そうでない関数にしてコンパイルすると、
main = "fail"
Prelude> :!ghc -o fail fail.hs
fail.hs:1:0:
Couldn't match `IO a' against `[Char]'
Expected type: IO a
Inferred type: [Char]
In the first argument of `GHC.TopHandler.runMainIO', namely `main'
When checking the type of the main function `main'
IO aでないとダメだって注意される。
ここで、Cを知っている人は比べてみて欲しい。
#include <stdio.h>
int main(void){printf("ゴッゴル");printf("ヤッヒョイ");return 0;}
//動くかな、これ。
Cの関数も、文字を表示するだけのプログラムで、使いもしない返り値を要求される。
Cの場合は、main関数の返り値の型は気にしないけど、haskellの場合はIO型になるんだ。
IO型というのはいまいち分からないけど、普通の型とは違うようだね。
次はその辺りを調べてみようかな。
と、この先は、さんざん分岐した方の説明も見てないと分からなくなるから、選択肢を拡げるのは一時停止。
他の経路と合流して次の段階に進もう。次は
入出力にしよう。
最終更新:2007年09月27日 06:30