HaskellでHello World!
こんばんは、south37です!
最近はHaskellネタばっか書いてる訳ですが、ここでいよいよ「Hello World」をしてみたいと思います!待ちに待ったHello Worldですよ!楽しみですね!!
...と喜ぶのは構わないですが、ここで一つ疑問が出てきます。他の言語なら真っ先にやるような「Hello World」を、なぜ今更やるのでしょうか?「Hello World」はそんなに難しい事なのでしょうか?他の言語では、とてもそうは思えませんでしたが?
...今回は、そのへんの疑問にもお答え出来たらいいなと思います!
何はともあれHello World!
さて、案ずるより産むが易しという言葉もありますし、とりあえずやってみましょう!まずは、次のコードを適当なファイル名で保存します。今回は、helloWorld.hsとでも名付けましょう。
main = putStrLn "Hello World!"
次に、シェルからghcコマンドを使ってhelloWorldプログラムをコンパイルします。
ghc --make helloWorld
そうすると、helloWorld
という名前の実行ファイルが出来ているはずです。最後は、これをシェルから実行します。
./helloWorld > Hello World!
ハイ、これだけです!一瞬で終わってしまいました。思った以上に簡単でしたね!!
では、何故こんな簡単な事を、これまでやってこなかったんでしょうか?
その疑問に答える第一歩として、まずは、helloWrold.hsに出てきたパーツ一つ一つについて考えてみましょう。main
はただの変数名、"Hello World!"
もただString
型の値を生成するリテラルであると思うと、注目すべきはputStrLn
だと分かります。では、putStrLn
の正体は何なんでしょうか?
入出力の「型」と「関数」
実は、putStrLn
はただの関数です。helloWorld.hs
の中では、putStrLn
が"Hello Wrold!"
というString
型の値を受け取り、返した値にmain
という名前がつけられているだけです。では、putStrLn
の返す値とは何なんでしょうか?
実は、putStrLn
が返すのはIO ()
型(()
はunitと呼ぶ)を持つ値であり、そのようなIO a
型の値は「I/Oアクション」と呼ばれます。I/Oというのは入力(Input)、出力(Output)のI/Oで、要するに外界との入出力を行うのが「I/Oアクション」です。
Haskellでは、「I/Oアクション」であるような値を特別扱いしていて、main
という名前がつけられるとその「I/Oアクション」が実行されます。例えば、putStrLn
は引数としてString
を受け取り、受け取ったString
を標準出力へ出力するという「I/Oアクション」を返します。
つまり、上記の例では
putStrLn :: String -> IO ()
のような型を持つputStrLn
が"Hello World!" :: String
を受け取って、「Hello World!を標準出力へ出力する」という「I/Oアクション」を返し、それにmain
という名前がつけられた為に実行時にHello World!の出力が行われた訳です。
要は、入出力もただの値という事です。何だか正体が見えてきましたね!
今回は「I/Oアクション」を返すものとしてputStrLn
だけを見ましたが、この他にも外部からの入力を行う為のgetLine
関数や、複数の「I/Oアクション」を糊付けして一つの「I/Oアクション」とする為の「do記法」などがあります。
結局、何が難しかったの?
ざっくりまとめると、HaskellにおいてIOを行うのは、コードとしては簡単です。ただ、その型についてちゃんと理解するのは、意外と大変だったりします。今回は最もシンプルな例でしたので理解しやすかったですが、次回以降、Monadとかその辺の話もしていこうと思います。
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (52件) を見る