Just $ A sandbox

プログラミングと計算機科学とかわいさ

最も素敵な言語とは?(函数型言語とは何なのか)

函数型言語とは何なのか

函数型言語、という名前くらいは皆さんご存知だと思いますが、しかし使ったことがない人は多いと思います。
入門書は山のように有りますが、「なぜ函数で記述するの?」ということが分からなければそれらを読み進めることも難しいと思います。
という訳で、函数型言語に至るには何があったのかを考えてみることにします。

いろいろな言語を通して

皆さんがどんな言語を使っているのかは分かりませんが、と書いた所でそういえばどんな言語が人気あるのかの調査があったことを思い出しました。
TIOBE Software: The Coding Standards Company

2012/9/16現在はやはりというべきか、上位にはC系列、JavaLL系の言語が上位にランクインしています。

さて、最も素敵な言語とはなんでしょうか。
もちろん、「どれだけシェアがあるか」で行けば上のような言語でおしまいなのですが、さて皆さん、ふつうにプログラム組むか、ってなった時に生のC言語に手が伸びる人はあまり居ないのでは、と思います。また、webアプリでなければPHPを使うことはしませんし、iOS用のアプリを作るのでなければObj-Cなど使えませんね。

何が言いたいのかというと、「言語として洗練された(人間にとって組みやすい)」ものはどれか、という話です。
ここでは恐らく多くの方にも馴染みのある何で言語を記述するか、ということで比較をしたいと思います。

  • 命令型言語:命令によってプログラムを記述します
    • Assembly, C, Basic...
  • オブジェクト指向言語:オブジェクトによってプログラムを記述します
  • 函数型言語:函数によってプログラムを記述します*1

命令型言語は全てのもの(PRINT, IF, FORなど)が命令でできていますし、オブジェクト指向言語もそうです。
具体的にコードをみることにすれば、例えばpythonですと、

def double(n):   # これは函数です
    return n*2   # 与えられた数の2倍を返します

print double(10) # もちろん"20"が表示されます
a = double(10)   # 20をaに代入します。数値、及び変数はどちらもオブジェクトなのでこれが可能です
a = double       # double函数をaに代入します。函数、及び変数はどちらもオブジェクトなのでこれが可能です
print a(10)      # aはdoubleと同じ物を指すので()付きで函数として呼ぶことができます 結果はもちろん20になります

double = 3       # 函数に数値を代入します。
print double     # 函数は数値オブジェクトになったので3が表示されます

上のように、全てのものは「オブジェクト」として扱われるので、函数に値を代入することも可能です。

上のものにはC++Javaをあえて記述しませんでした。何故でしょう?
それはC++Java命令などを記述できますがオブジェクトという概念も備えているのでグループ分けが微妙だからです。*2

pythonは(rubyもです)上のような、「全てのものがオブジェクトなので」柔軟な書き方が出来る反面、しかしこれはコンパイルエラーの検出を困難にします。つまり動的な型付けのせいで実行されないとエラーが出るかどうかがわからない部分があるので、コードの動作が保証しにくいのです。

これを解決する素敵な方法があります。それはオブジェクトという概念に「静的な(明示的な)型付け」を導入することです。

  • 値、変数はオブジェクト
  • 函数はオブジェクトをn個受け取りオブジェクトを返すオブジェクト

プログラムを記述するときに、どれが変数でどれが函数(またそれはいくつの変数を受け取るのか)なのかを明示させることにしましょう。
こうすれば、コンパイル時に型チェックを行うことができるので、コードの動作保証がしやすくなりますね!

さて、話は変わります。
上の「オブジェクト」の部分を全て「ある型を持つ函数」に置き換えて下さい。

おめでとうございます!あなたは函数型言語erとしての第一歩を歩み始めました!!

これが函数型言語です。正確に言えば型付きλ計算のやっていることになります。
全ての物を函数として表現する手法とは、オブジェクト指向言語の先にあります。むしろオブジェクト指向言語の最大の弱点である「柔軟さから来る不確定性」を補うものとして考えることができます*3

函数であることの意味はもうひとつだけあります。
基本的にはオブジェクトと変わらないんですが、厳密に「写像としての函数」のみを許容することでプログラムの厳密性を保証してくれます。
例えば、文字を受け取って画面にそれを表示するとか言うのはどう見ても写像では無いので厳密な函数型言語では記述してはいけません。これは函数ではなくて命令ですから、別の概念ですね。

「じゃあprintしたい時にどうするの?」「そもそも代入って函数じゃ記述できないよね」「そこまで言語の記述を束縛して使い物になるの?」等々の疑問を持った方は、是非、これらのことを念頭に置いて入門書を開いてみて下さい。

きっと素晴らしい世界が待っていることと思います*4

*1:何でここで旧字体の「函数」という表記をしているかというと、趣味です。値を入れたら値を返す箱というイメージをより的確に反映しているというのが個人的に何となくしっくりくるからです。

*2:とくにC++などは函数型言語としての使い方も可能であるためさらにグループ分けが曖昧なので記述を控えました。

*3:もちろんこれはあくまで考え方の一つであり、歴史的にこのような変遷をたどったわけではありません

*4:今回は完全にプログラム的な視点から函数型言語を捉えましたが、数学的な(というより論理学的な)視点から捉えることも可能ですし、そちらも興味ある方は是非チャレンジしてみて下さいね