質問: 関数型プログラミングを勉強しようと思っているのですが、LISPとHaskellどちらが良いのでしょうか? 詳しい方いらっしゃいましたら、教えて下さい。 よろしくお願い致します。
回答: Q: LISPとHaskellどちらが良いのでしょうか? A: **両方するのが良いです。** では、だめですよね。はい、ということで、始めにどちらをすべきかと言う指針を示したいと思います。 ### LISP Cと同じぐらい、一度はやっておけという言語です。さて、最初の関数型プログラミングの考え方はLISPから始まったと言っても過言ではありません。なら、関数型プログラミングを学ぶにはLISPが良いんだな...という結論づける前に、**どのLISPで?**という問題が立ちはだかります。単にLISPと言っても、たくさんの方言があります。有名なのは下記でしょうか。 * 純LISP ... LISPとして成り立つ最低限の機能に絞ったLISP。実用性は皆無。論文を書くために存在すると思われる。実装は可能とあるが、実装はあるのだろうか? * Scheme ... 主に教育分野で使われる。学習には一番向いているのかも知れない。ついでにSICPも読んでおくと、プログラミングに関する造詣が深まると思われる。実装がたくさんあるし、なにやらバージョンで揉めたこともあるようだ。 * Common Lisp ... たくさんある方言をまとめて、統一しようとしたLISP。実用性第一。しかし、そのため、関数型プログラミングだけではなく、手続き型プログラミングのパラダイムも取り入れてしまっている。 * Emacs Lisp ... Emacsの拡張言語として使うためのLISP。Emacs使いであれば必須。 * Clojure ... JavaVMや.NET上で動くLISP。一時期JavaVM用言語として持て囃されていたが、最近はScalaやKotlinに押され気味のような気がする。 学習目的ならSchemeが良いのではないかと思います。ただ、実用性で言えば、Common LispやEmacs Lisp、Clojureの方があると思います。注意して欲しいのは、これらのLISP方言のほとんどが純粋関数型プログラミング**ではない**ということです。変数の再代入など、手続き型のような処理も**できてしまいます**。また、末尾再帰の最適化や遅延評価などが必ずしもあるとは限りませんし、モナドを言語としてあまり考慮していません。 ラムダ式や再帰関数、リスト処理といった所を学習するのであれば、LISPでも十分でしょう。しかし、全てが純粋関数型プログラミングではない事に注意すべきです。単純なハローワールドである`(display "hello, world!\n")`(Schemeでの記述)ですら副作用の塊であり、関数型プログラミングではありません。IO処理は手続き型の方が簡単で、理解しやすいですが、全体が結局どこか混ざった記述になってしまうと言うことを考えておくべきです。 ### Haskell 正真正銘の純粋関数型プログラミング言語です(実際には副作用を伴う関数が存在しますが、通常は「禁じ手」扱いです)。末尾再帰の最適化は当たり前なので、再帰関数を作るのは普通のこと。遅延評価による処理の最適化。モナドを用いた、副作用に対する純粋さの維持。そして、Haskellには手続き型にあるような変数の再代入などという不純物はありません。ですので、**関数型プログラミングを強要される**と言うところが、最大の利点です。 Haskellを使うと、手続き型の考えは全く通用しません。ループにするには再帰にするしかありませんし、配列はその中身を変更することもできませんので、新たに配列を作って行くようにするしかありません。関数型プログラミングの考えでアルゴリズムを考えないと、まともなプログラミングが一切できません。今までの物が使えないというのは欠点のように思えるかも知れませんが、逆に、今までの物を一旦捨てて、関数型プログラミング**だけ**を学ぶには、手続き型で考えてしまう甘えなくすには、とても良い言語だと思います。 ### 結論 好きな方から始めた方が良いかと思います。Cのような手続き型プログラミングしかしたことがない人から見ると、どちらも戸惑いは大きいです。甘えをなくしたいのであればHaskell、モナドとかは置いといて、ラムダ式や再帰関数、リスト処理などをまずは学びたいならLISPが良いのではないでしょうか。 でも、結局は、最終的に**どちらもすべき**ということです。