実践的な Haskell の本

Perl6 は何年経っても正式にリリースされません。そんな Perl6 を Audrey Tang さんは、たったの数ヶ月で作りました。その実装は Pugs と呼ばれています。短期間の開発を可能にした秘密兵器は Haskell です。

その Audrey さんが、2006年に日本で Haskell について説明してくれました(資料)。残念ながら、そのころの僕は Haskell に興味がなかったのでチュートリアルは受けていませんが、その概要にはこう書かれています。

コーナーケースを探すのにユニットテストを書くのに疲れた? QuickCheck を使ってコンピュータに書かせちゃいましょう。正規表現ベースのパーサはメンテナンスしにくいのに気づいた? Parsec を使って 15分で Perl6 の完全なパーサを書く方法を勉強しましょう。デッドロックやレースコンディションはもううんざり? STM が concurrency 問題は全部解決してくれます。 XS や SWIG が頭痛の種になってる? FFI なら C コードを簡単に、かつ安全に埋め込めますよ。

キーワードとして挙げられている QuickCheck、Parsec、STM、FFI に興味が湧きましたか? こんな実践的な技術を網羅している本が、Real World Haskell です。

Real World Haskell: Code You Can Believe In

Real World Haskell: Code You Can Believe In

この本の原稿は、インターネットで公開され、たくさんのコメントをもらった後に、紙媒体として出版されました。

僕はオンライン版の Using Databases の章を読ませて頂いたおかげで、Haskell から SQLite を操作できるようになったので、amazon で注文を受け付け出したときにすぐ予約しました。(届くまでに3ヶ月かかりましたが。。。)

この本は670ページもあり、読み終わるのを待って書評を書くと旬を逃してしまいそうです。そこで、フライングで申し訳ないのですが、斜め読みした時点での書評を書いておきます。

内容

僕は、この本には Haskell の基礎は書かれていないのだろうと勘違いしていました。しかし、最初の4章には基礎が書かれており、その内容を読んで感心しました。

Haskell でまず躓くのは、for 文がないことです。繰り返しは再帰で実現すると言う、分ってしまえば当たり前のことに気付くまでに時間がかかるのです。でもこの本では、実際に C の for 文を Haskell の再帰に直す方法がちゃんと説明してあります。

代数データ型についてもそうです。Cの構造体や共用体と対比しながら、Haskell の代数データ型を解説しています。(C を知らない人には、分りやすいとは言えないかもしれません。)

Audrey さんが挙げた QuickCheck、Parsec、STM、FFI にも、もちろん触れています。僕は Parsec に詳しいので、Using Parsec 章について感想を述べておきます。

Parsec にはチュートリアルがありますが、内容が古く、また間違いもあり、例として挙げられているコードは動かないことがあります。一方で、Using Parsec の章だけを読んでも使いこなせるようになるのは、ちょっと無理がある感じです。

ですので、まず Parsec のチュートリアルを「還暦プログラマの挑戦(Haskell に挑む)」を参考にしながらやってみて、次に Using Parsec の章を読むといいでしょう。チュートリアルでは数式のパーサーを作るだけで終わってしまいますが、Using Parsec の章には、JSON など実践的な例が載っています。

Real World Haskell で必見なのは、Monads の章でしょう。みなさん、モナドを理解できてますか? 分りやすい解説って、ほとんど見たことないですよね?

僕は1年に渡って調べた結果、ようやく分り、僕ならこう説明すると思っていました。

  • 関数型プログラミングの心は、小さな関数を書き、それをつなぎ合わせることだ。
  • Haskell では演算子を自由に定義できる。この演算子は、データだけでなく関数も連結できる。
  • (データも含む)関数をつなぎ合わせる演算子をコンビネータという。
  • コンビネータはとっても便利。探索とかパーサーとかを考えるとよく分る。
  • でも、問題領域ごとに独自のコンビネータを作っていると煩雑になる。
  • だから、コンビネータを作る際の指標が欲しい。
  • コンビネータの性質を抽象化していくと、カテゴリー論でいうモナドになることが分った。理解できなくてもいいけど、簡単に言うと群みたいな感じ。群で言う演算子「・」には、よい性質があるでしょう?
  • 数学的な裏付けをもとに、「標準化されたコンビネータ」が ">>=" (bind)。
  • という訳で、コンビネータを作る際は >>= にできないか(モナドにできないか)を考えてみる。
  • 標準化したのだから、1つだけフレームワークを与えておこう。それが do。
  • do だと、あたかも命令型言語のように書けて便利。
  • モナドにできれば共通のフレームワークである do が使えるよ。

Monads の章は、ほとんど同じように説明されていて、ビックリしました。

Real World Haskell の残念なところを 2 つ挙げておきます。

  • unsafePerformIO について解説がない
    • これがないと IO モナド地獄から抜け出せない
  • Haskell Server Pages が取り上げられてない

はい。単なる欲張りが重箱の隅をつついているだけなので、気にしないで下さい。

Real World Haskell は、その名の通り、Haskell で実践的なプログラムを書こうとしている人にとって必須です。