関数型言語
テンプレート:独自研究 テンプレート:プログラミング言語 関数型言語(かんすうがたげんご、functional language)は、関数型プログラミングに向いた特徴を持つプログラミング言語、関数型プログラミング言語である。引数に関数を作用(applicate)させて計算をおこなうことから、作用型言語(applicational language)ともいう。データフロープログラミング言語も関数型言語の一種である[1]。
関数型プログラミング
ここでの「関数」とは、数学でいう「関数」であり、手続き型プログラミングなどにおける「関数」ではないことをまず注意する。典型的には原則としては副作用がないものであることが挙げられる。これを誤解し、また、Pascalでは「手続き」と呼ぶ値を返さないルーチンもC言語では「関数」と呼ぶから、といった間違った理由から、(Pascalは手続き型言語で)C言語は関数型言語などとしている文献もある[2]が誤りである。
関数への引数がプログラムへの入力で、関数を引数に作用させて評価して得られる値がプログラムからの出力であるとすると、コンピュータプログラムはある種の関数であると考えることができる。ここで、入力や出力は記憶装置中のファイルのようなものばかりではなく、マウスの動きの情報といった入力や、画面への表示といった出力も考えられる(極端には、一般的な機械語の命令も、レジスタやメモリのようなコンピュータの内部状態の、命令実行前の全状態を入力とし命令実行後の全状態を出力とする関数である、と考えることも不可能ではない。ここで「全状態」としていることに注意。たとえばBASIC言語の poke()
関数によるメモリの書き換えは、メモリの状態は引数にも返す値にも含まれず、副作用によるものであり、 poke()
関数はここでいう「関数」ではない)。
複雑なコンピュータプログラムに相当する関数を作るために、第一級関数を扱えることなどが関数型言語には必要である。概要の節で詳説する。
他のプログラミングパラダイムとの関連としては、関数型プログラミングは論理型プログラミングと同じく宣言型プログラミング・非手続き型プログラミングで、手続き型プログラミング・命令型プログラミングと対立する。
概要
関数型言語には、関数型プログラミングのために、まずは第一級関数が必要不可欠である。他にカリー化などの機能を持つことが多い。静的型付けの言語の多くは型推論の機能を持つ。理論的な計算モデルとしてはラムダ計算や項書き換えをベースとする。
純粋関数型言語では、参照透過性が常に保たれるという意味において、全ての式や関数は副作用を持たない。入出力などのために、多くの純粋関数型言語は正格性に関して非正格であり、引数はデフォルトで遅延評価である。また入出力などを参照透過性を保ったまま実現するために、たとえばHaskellではモナド、Cleanでは一意型(w:Uniqueness type)という特殊な型を通してでのみ入出力などを扱えるようにしている。
非純粋関数型言語では、参照透過性を壊す、副作用があるような式や関数も存在する。Lispなどでデータ構造の破壊的変更などの副作用を多用したプログラミングをおこなうと、それはもはや手続き型プログラミングである。非純粋関数型言語は多くが正格性に関して正格であり、評価戦略としては正格評価(先行評価)である。無限リストのような技巧を使うために、明示して遅延評価をおこなわせるための機構を持つことが多い。
JavaScriptなど近年の高水準言語には、関数型言語の機能や特徴を取り入れているものが多いが、変数の値やオブジェクトの状態を書き換えるプログラミングスタイルを通常とするため、関数型言語とはしないのがもっぱらである。一方LISPは、その多くが副作用のある式や関数が多数あり、手続き型スタイルでのプログラミングも可能だが、理論的なモデル(「純LISP」)の存在や副作用を使わないプログラミングが基本であること、歴史的理由などから、関数型とされる。
歴史
FORTRANには、関数(ここでは副作用のあるものを含む意味で)を定義できる、「ADD A, 1」のような形ではなく「A = A + 1」のように式で計算を指示できる、といった特徴もあったが、基本的には手続き型プログラミング言語であった。
LISPは、その基本機能のモデルとして関数型の純LISPを持つなどといった特徴がある、最初の関数型言語である。こんにち広く使われているLispのうち特にSchemeは関数型としての特徴が強い。
現代的な関数型言語の祖としてはアイディアが1966年に発表されたISWIMが挙げられるが、1970年前後までは関数型言語の歴史はLispの発展が主である。1970年代にプロジェクトが開始されたw:Logic for Computable Functionsのための言語としてMLが作られている。
またLISPにおいて、変数のスコープに静的スコープを採用したSchemeが誕生したのが1975年である。
1977年、FORTRANの設計とBNFの発明の業績でこの年のチューリング賞を受賞したジョン・バッカスは、Can Programming Be Liberated From the von Neumann Style?: A Functional Style and Its Algebra of Programs[3]と題した受賞記念講演で関数型プログラミングの重要性を訴えた。講演ではFPという関数型言語の紹介もした(サブタイトルの後半の「プログラムの代数」はこれを指す)が、これはAPL(特に、高階関数の意味がある記号(APLの用語ではoperator(作用素)という))の影響を受けている(APL自体はふつう関数型とはされない)。
バッカスのFPは広く使用されることはなかったが、この後関数型言語の研究・開発は広まることとなった。1985年にMirandaが登場した。1987年に、遅延評価の純粋関数型言語の標準の必要性が認識されHaskellの策定が始まった。1990年にHaskell 1.0仕様がリリースされた。同じく1990年にはMLの標準であるStandard MLもリリースされている。
Cleanは1987年に登場したが、発展の過程でHaskellの影響を受けている。1996年に、ML処理系のひとつであったCamlにオブジェクト指向を追加したOCamlが登場した。
21世紀に入ると、Java仮想マシンやCLIに関数型言語を実装しようという動きがあらわれ、Scala・Clojure・F#などが登場した。