数当てゲーム in Haskell

純粋関数型言語を使う上でもっとも問題となるのはやはりIOだろう。
現在用いられている方法はおおよそ3つある。

  • ストリーム
  • モナド
  • 一意性型付け

Haskellは主にモナドを使うわけであるが、
入出力が文字列に限定される場合はinteract*1
簡単にモナド→ストリームの変換ができる。
そこで、コンソールアプリ習作の大定番、
数当てゲームをHaskellで実装してみた。
(実装してみたというか、ちょっと前に作ったネタだけど)
ストリームIOである。
見てもらえば分かると思うが、むちゃくちゃ簡潔。
数当てゲームというものが見事に"記述"できている
のが分かると思う。
今まで触った言語の中でもきわめて短い部類にはいるのではなかろうか。

module Main(main) where
import Random

main = do ans <- randomRIO (1,100)
          interact $ unlines.game ans.map read.words

game :: Int -> [Int] -> [String]
game ans ls = "Please Input Number. (1-100)":gen ls where
  gen (x:xs) | x == ans = ["Collect Answer!"]
             | x  > ans = "Answer is smaller.":gen xs
             | x  < ans = "Answer is bigger." :gen xs

gameという関数が数当てゲームを記述している。
解答と入力される数字の列を引数にとって、
しかるべきリアクションのリストを返す。
入力が準備され次第構築され、
出力はそれに応じて生成される。
上記のようなソースできちんとインタラクティブ
プログラムになるのである。
これは驚くべきことではないだろうか?

*1: (String -> String) -> IO() の型を持つ関数。渡された関数に標準入力から取ってきた文字列を渡し、その結果を標準出力に出すようなコマンドを作る