HaskellでIO!

どうもこんばんは、south37です。今日も前回に引き続き、Haskellにおいてどうやって入出力を実現しているのか、見ていきたいと思います。

do構文を使おう

さて、一度前回のおさらいをしておきましょう。前回は、Hello Worldを出力するプログラムを作ったのでした。

main = putStrLn "Hello World!"

上記のコードでは、putStrLnStringを受け取って「I/Oアクション」、すなわち「実行されると副作用を含む動作をするもの」を返し、それに「main」という名前がつけられています。「I/Oアクション」に「main」という名前がついている為に、上記のコードをコンパイルして実行すると「標準出力へ文字列("Hello World!")を出力する」という動作が行われます。

では、複数の「副作用を含む動作」を行いたい時は、どうしたら良いのでしょうか?「main」という名前は一つの「I/Oアクション」にしかつけれないのに?

心配ありません。実は、Haskellにおいてはとても便利な構文である「do構文」というものが用意されています。書き方は単純で、doの後に実行したいI/Oアクションを返す関数をただ並べて行くだけす。

main = do
  putStrLn "Yeah!"
  putStrLn "Wow!"

これをコンパイルしてterminalで実行すると、標準出力へ

Yeah!
Wow!

と出力されます。Yeah!ものすごく簡単でしたね!!

標準入力を使おう

次は、少しinteractiveなプログラムを作ってみましょう。

main = do
  putStrLn "Hello, what's your name?"
  name <- getLine
  putStrLn ("Hey " ++ name ++ ", you are cool!")

新しい関数getLineと、新しい構文<-が出てきました。これらは何をするのでしょうか? 見た目で何となく想像すると、「Hello, what's your name?と名前を聞かれて、名前を入力するとHey (名前), you are cool!と出力される」プログラムのように見えます。実は全くその通りです!

何が起きているのか、順に見て行きましょう。

getLineは標準入力(デフォルトではシェルでのユーザーからの入力ですね)を受け取って、その文字列をくるんだIO String型の値を返す関数です。より正しく言うと、「標準入力を受け取る」という副作用を実行するIO String型の「I/Oアクション」を返す関数です。

<-という構文は、IO String型のようなIO a型の値から中身のa型の値を取り出して、変数に束縛する為に用意されています。上の例では、入力として受け取った文字列が、nameという変数に束縛されています。

これで、入出力をつかさどる「I/Oアクション」が何故IO型では無くIO a型を持つのか分かったと思います。getLine :: IO Stringの様に、入出力の結果をIOでくるんだ値が必要となるからです。

まとめ

今日は、複数の「I/Oアクション」をまとめる為の「do構文」と、interactiveなプログラムを書く為に「標準入力」を受け取る方法、およびIOにくるまれた値を変数に束縛する方法を学びました。次回は、「do構文」が本当は何をしているのか、特に「モナド」がどう絡んでくるのかについて、まとめてみたいと思います。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!