関数型言語の勉強方法について人力検索で質問してみた

関数型言語(プログラミング言語Scheme, Haskellなど)を勉強しようと思っています。 初心者にも関数型言語のメリットや考えかたがスラスラ分かる勉強の材料を教えてください。 言語の習得よりも、関数型言語の考え方の習得に重きを置いています。 例えば - この本を読め - このサイトを読め のように、入門から実用レベルまできちんと筋の通ったものをお願いします。 ちなみに 以前Schemeを勉強しましたが末尾再起辺りでなんとなくうやむやになってしまいました。 あと「計算機プログラムの構造と解釈」は僕には難しすぎでした。

Haskellプログラミング

「情報処理」で連載されているHaskellプログラミングの連載を読むことができます。最初の方で関数型について説明されています。

プログラム工学VI 授業関連資料

大学での講義資料です。

OCaml でよければ

Objective Caml 入門

は非常に優れた入門です。

関数型言語的な考え方はよく理解できると思います。

なかなか難しい質問です。一冊あるいは一サイト、決定版と言えるようなものは思い当たりません。しかし関数型言語やそのアプローチについては最近関心が高まりつつあるようで、ギャップを埋める入門書が徐々に出てくると思われます (例えば青木さんの「ふつうのHaskellプログラミング」 http://i.loveruby.net/d/20060323.html#p02 。5月末出版だそうです)。というわけで、「これ!」という一冊の本で勉強したいのならもう少し待ってみるというのも手です。

さて、現在ある材料で勉強するとして、higeponさんのリクエストを考えてみます。

[とっかかり]

関数型言語の難しさは、既に手続き型言語を使いこなしている人と、関数型言語で初めてプログラミングに触れる人とで違うのではないかと思われます。既に手続き型言語を知っている場合、その知識が関数型言語を使うにあたって邪魔になる可能性があります。そこで、どんな材料で勉強するにしても、まず一度、手続き型言語でマスターした概念をわきに置いてみることをお薦めします。具体的には…

  1. 「こう書くと余分なメモリを食うのでは」とか「ここでコピーするともったいないな」とか「同じ計算を何度もしてるんじゃ?」みたいな、貧民的発想をいったん捨てましょう。無限の速度と無限のメモリを手にしているのだと思い込み (あるいは、処理系がものすごく賢くてうまいことやってくれるんだと信じて) **最初は** ナイーブなコードでいいと開きなおります
  2. 手続き型言語でループを書くとき、アセンブラででもなければ条件分岐とgotoは使いませんよね。forやwhileなどを使うと思います。定型的な処理にはイディオムがあるわけです。関数型言語にもイディオムがあり、それは手続き型言語のものとかなり異なります。手続き型言語の知識をあてはめようとするのではなく、例を読んだり課題を解いたりする過程で関数型言語のイディオムを意識的に覚えるようにします。
  3. 変数は値を入れる箱ではありません。値、あるいは式そのものに便宜的に名前をつけているだけです。
  4. 計算は、つねに関数に値を渡し、その戻り値を使うことで進行します。戻り値は複数あるかもしれません。
  5. 構造を持つデータの各要素に対して処理をしたい場合には、(a)その構造全体を一気に処理できる関数(例:map, fold等)を使うか、(b)その構造を「頭」と「残り」に分解し、「頭」を処理して、「残り」は自分自身を再帰で呼んで処理させ、最後に結果を合成します。

まあこんな感じのことを頭において、

などに練習問題も含めてトライしてみたらいかがでしょうか (Schemeの例ばかりですが、他の関数型言語にも似たようなものがあると思います)。確かにこれらは言語の習得 (HtDPはもっと一般的ですが) に重点を置いていますが、上に挙げたような「違う見方を得る」ことに注意していると、得られるものが違ってくると思います。

[舞台裏]

富豪的とは言われても、裏でプログラムがどう動いているかは気になるもの。特に手続き型言語でがりがりプログラムを書いていた人にとっては、関数型言語のプログラムが実際にどのような手順で実行されているかを知ることによって、関数型言語への理解が深まることもあります。

それには処理系を読んでみるのが一番なのですが、フルセットの処理系はコードベースも大きくなりがちなうえ、色々なおまけがついていて本質的なところが見えにくいかもしれません。サブセットのMLコンパイラの実装を解説したこれなんかは参考になるかもしれません。

コンパイラを読むことで、関数型言語であってもある程度どのような機械語に落ちているかを意識することができるようになります (関数型言語のイディオムを習得した後でこの段階に進んで下さい)。


[実用へ]

最後に関数型のメリットですが、これは中規模以上の実用的なプログラムを書いてメンテナンスしてみないと肌で感じるのが難しい領域だと思います。大規模プログラミングで最も重要な要素はモジュラリティであり、それが関数型プログラミングの最大の利点のひとつでもあるからです。この論文はその点を簡潔に述べています:

ですが、この論文を「そうだよな〜」と納得しながら読める人は、既に関数型言語をよく知っている人だけなのではないか、という気がします。ですので、関数型言語についてのメリットを本当に知りたいと思うなら、それによってプログラムを書いてみるしかないのではないかと思います。

http://www.hyuki.com/haskell/200412

Haskellのコードが載っています。

考え方の参考になるのではないでしょうか?

http://www.sampou.org/haskell/tutorial-j/goodies.html

入門書として読んでますが、他にも読みたいです。


回答をお待ちしています。
気軽にコメント欄に書いていただくというのもありです。
よろしくお願いします。