Hello, World!

Haskell の利点とかインストールはさくっと読み飛ばして p.17 の Hello,World! 。

main = putStrLn "Hello, World!"

ghcコンパイル。うん、ちゃんと動く。OCamlで書くと

let _ = print_endline "Hello, World!"

だな。
ここで 1 章が終わって 2 章へ。UNIX コマンドを作る。と、その前に Hello, World! の復習から。変数の定義、mainアクション、関数適用の説明など。main は関数ではなくてアクションというものらしい。これは putStrLn が返す値なのかしらん。

cat コマンドを作る。

main = do cs <- getContents
          putStr cs

do を使うと上から下に順番に実行されるとのこと。多分モナドと関係ある。そして、<- で束縛。これも多分モナドやらなんやらが絡んで来るんだろう。getContents は標準入力から全部読み込むアクション。でもその場で実際に読み込まれるわけではない。実際、

main = do cs <- getContents
          putStrLn "Foo"
          putStr cs

とすると、入力される前に Foo が出力されているのがわかる。
オフサイドルールはいいなあ。OCamlの begin/end は超絶美しく無いから。(かといって括弧を使うのはもっとダサい)
次はリスト処理。文字列が文字のリストなのは便利そう。OCaml でもよく string を char のリストにして処理することが多いが、 explode/implode が標準でないのはどういうことか。しかも string が mutable なんて最悪だ。Pervasives.input は許しがたいぞ。
で、length 関数とか lines 関数とか。$ が便利そう。OCaml にも欲しい。でも

let ($) f x = f x

とかやっても駄目。$ は左結合になるから、例えば

print_endline $ string_of_int $ List.length $ [1;2;3]

((print_endline $ string_of_int) $ List.length) $ [1;2;3];;

と解釈されてしまう。SMLなら演算子の優先順位と結合性を決められるから、

fun op$ (f,x) = f x;
infixr 0 $;

print $ Int.toString $ length $ [1,2,3]

とでもしてやればいい。
よし、今日はここまでにしよう。なんか ML についてばっかり書いてる気もするが。