「関数型プログラミング」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
編集の要約なし
タグ: Refタグつき記述の除去 ビジュアルエディター
特徴
4行目: 4行目:
'''関数型プログラミング'''(かんすうがたプログラミング、{{lang-en-short|''functional programming''}})は、[[プログラミングパラダイム]]の一つであり、[[ソフトウェア工学]]における主にプログラムリスト作成とコード記述の分野で用いられる考え方である。一説には[[数理論理学]]の[[ラムダ計算]]をモデルにして考案されたと言われる。
'''関数型プログラミング'''(かんすうがたプログラミング、{{lang-en-short|''functional programming''}})は、[[プログラミングパラダイム]]の一つであり、[[ソフトウェア工学]]における主にプログラムリスト作成とコード記述の分野で用いられる考え方である。一説には[[数理論理学]]の[[ラムダ計算]]をモデルにして考案されたと言われる。


ここでの'''関数'''(''function'')とは、入力値を変換式に与えて出力値を導き出す仕組みのプログラム構文を指す。関数型プログラミングの世界では、大局的にはコード(変換式)とデータ(値)が完全に分離されている。実行中におけるプログラム環境の変化は副作用(''side-effect'')と呼ばれ、この副作用に関する一切の情報はデータ側に蓄積されてコード側は保有しない。またデータは生成されるのみで変化する事はない。変換式に与えられた入力値に次の副作用を加えて新たに生成された出力値を、再帰的に変換式に与え続けて最終的な最適解の値を得るのが、関数型プログラミングの基本的な流れとなる。
ここでの'''関数'''(''function'')とは、入力値を変換式に与えて出力値を導き出す仕組みのプログラム構文を指す。関数型プログラミングの世界では、大局的にはコード(変換式)とデータ(値)が完全に分離されている。実行中におけるプログラム環境の変化は副作用(''side-effect'')と呼ばれ、この副作用に関する一切の情報はデータ側に蓄積されてコード側は保有しない。またデータは生成されるのみで変化する事はない。入力値を与えた変換式の演算結果今回の副作用情報上乗せして新たに生成された出力値を、再帰的に変換式に与え続けて最終的な最適解の値を得るのが、関数型プログラミングの基本的な流れとなる。


== 特徴 ==
== 特徴 ==
関数型プログラミングの理念(在り方)は、[[参照透過性]](''referential transparency'')、情報構造体(''data structures'')、[[再帰]](''recursion'')、[[評価戦略]](''evaluation strategy'')の四点で表現できる。[[高階関数]](''higher-order functions'')、[[第一級関数]](''first-class functions'')、純粋関数(''pure functions'')、[[データ型]](''type systems'')も不可欠なものであるが、これらは実装法または最適化よりの考え方である。

=== 参照透過性 ===
=== 参照透過性 ===


=== 情報構造体 ===
=== 情報構造体 ===

=== 型理論 ===


=== 再帰 ===
=== 再帰 ===
17行目: 17行目:
=== 評価戦略 ===
=== 評価戦略 ===


=== 第一級関数と高階関数 ===
=== 高階関数と第一級関数 ===


=== 純粋関数 ===
=== 純粋関数 ===


=== 束縛変数と自由変数 ===
=== データ型 ===

=== その他 ===


== 概要 ==<!--関数型プログラミングではプログラムの構成にC言語のように関数を多用する<ref>The C language is purely functional http://conal.net/blog/posts/the-c-language-is-purely-functional</ref>。[[Wikipedia:検証可能性#通常は信頼できないとされる情報源]]-->
== 概要 ==<!--関数型プログラミングではプログラムの構成にC言語のように関数を多用する<ref>The C language is purely functional http://conal.net/blog/posts/the-c-language-is-purely-functional</ref>。[[Wikipedia:検証可能性#通常は信頼できないとされる情報源]]-->

2019年9月10日 (火) 01:57時点における版

関数型プログラミング(かんすうがたプログラミング、: functional programming)は、プログラミングパラダイムの一つであり、ソフトウェア工学における主にプログラムリスト作成とコード記述の分野で用いられる考え方である。一説には数理論理学ラムダ計算をモデルにして考案されたと言われる。

ここでの関数function)とは、入力値を変換式に与えて出力値を導き出す仕組みのプログラム構文を指す。関数型プログラミングの世界では、大局的にはコード(変換式)とデータ(値)が完全に分離されている。実行中におけるプログラム環境の変化は副作用(side-effect)と呼ばれ、この副作用に関する一切の情報はデータ側に蓄積されてコード側は保有しない。またデータは生成されるのみで変化する事はない。入力値を与えた変換式の演算結果に今回の副作用情報を上乗せして新たに生成された出力値を、再帰的に変換式に与え続けて最終的な最適解の値を得るのが、関数型プログラミングの基本的な流れとなる。

特徴

関数型プログラミングの理念(在り方)は、参照透過性referential transparency)、情報構造体(data structures)、再帰recursion)、評価戦略evaluation strategy)の四点で表現できる。高階関数higher-order functions)、第一級関数first-class functions)、純粋関数(pure functions)、データ型type systems)も不可欠なものであるが、これらは実装法または最適化よりの考え方である。

参照透過性

情報構造体

再帰

評価戦略

高階関数と第一級関数

純粋関数

データ型

その他

概要

関数型プログラミングでは関数を第一級オブジェクトとして扱う。理論的な計算モデルとして第一級オブジェクトとしての関数を扱えるラムダ計算項書き換えを採用している。

コンピュータプログラムは通例入力を受け取って何らかの処理を行ない、出力を返すことを目的として書かれる。数学の関数において、を入力、を出力と考えると、コンピュータプログラムはある種の関数であると考えることができる。ここで、入力や出力は記憶装置中のファイルのようなものばかりではなく、キーボードやポインティングデバイスによってユーザーから与えられる情報や、画面への表示といった入出力形態も考えられる。関数型プログラミングにおいては実際にそれらを扱う関数としてモデル化する。

純粋関数型言語では、参照透過性が常に保たれるという意味において、全てのや関数の評価時に副作用を生まない。純粋関数型言語であるHaskellCleanは非正格な評価を基本としており、引数はデフォルトで遅延評価される。一方、Idrisは純粋だが正格評価を採用している。入出力などを参照透過性を保ったまま実現するために、たとえば Haskell ではモナドClean では一意型英語版という特殊な型を通して一貫性のある表現を提供する。

非純粋関数型言語では、参照透過性を壊す、副作用があるような式や関数も存在する。LISPなどでデータ構造の破壊的変更などの副作用を多用したプログラミングを行うと、それはもはや手続き型プログラミングである。多くの場合、非純粋関数型言語の評価戦略は正格評価(先行評価)であるが、遅延評価する部分を明示することで、無限リストなどを扱えるものもある。

JavaScriptJavaなど近年[いつ?]高水準言語には、関数型言語の機能や特徴を取り入れているものがあるが、変数の値やオブジェクトの状態を書き換えるプログラミングスタイルを通常とするため、関数型言語とは分類されない。一方LISPは、その多くが副作用のある式や関数が多数あり、手続き型スタイルでのプログラミングがされることも多いが、理論的なモデル(「LISP」)の存在や副作用を使わないプログラミングが基本であること、ないし主には歴史的理由から、関数型言語だとされることが多い。なお、Pascalでは「手続き」と呼ばれるような値を返さないサブルーチンを、C言語では「関数」と呼んでいるが、これは単にルーチンについて、細分類して別の呼称を付けているか、細分類せず総称しているか、という分類と呼称の違いに過ぎず、「Pascalは手続き型言語で、C言語は関数型言語」[1]という一部の書籍に見られる記述は明確に誤りである。また、OCamlHaskellなどでは、「自明な値(例えば())を返す」と、値を返さない(Voidなど)は違うものであり、後者は停止しないか例外を出す(そのため結果がない)ようなプログラムを表す。

なお、「関数型言語である」と「関数型プログラミングをする」は同値ではなく、関数型には分類されない言語で関数型プログラミングをすること[2]や、関数型プログラミングを基本とする言語の上で他のパラダイムを実現する例もある[3]

データフロープログラミング言語も関数型言語と共通した特徴を部分的に持つ。

歴史

LISPは、その基本機能のモデルとして関数型の純LISPを持つなどといった特徴がある、最初の関数型言語である。今日広く使われているLISP方言のうち特にSchemeは関数型としての特徴が強い。

現代的な関数型プログラミング言語の祖としてはアイディアが1966年に発表されたISWIMが挙げられるが、1970年前後までは関数型プログラミング言語の歴史はLISPの発展が主である。1970年代にプロジェクトが開始されたロジック・フォー・コンピュータブル・ファンクションズ英語版のための言語としてMLが作られている。

またLISPにおいて、変数のスコープに静的スコープを採用したSchemeが誕生したのが1975年である。

1977年、FORTRANの設計とバッカス・ナウア記法の発明の業績でこの年のチューリング賞を受賞したジョン・バッカスは、Can Programming Be Liberated From the von Neumann Style?: A Functional Style and Its Algebra of Programs[4]と題した受賞記念講演で関数型プログラミングの重要性を訴えた。講演ではFPという関数型プログラミング言語の紹介もした(サブタイトルの後半の「プログラムの代数」はこれを指す)が、これはAPL(特に、高階関数の意味がある記号(APLの用語ではオペレーター(作用素)という))の影響を受けている。

バッカスのFPは広く使用されることはなかったが、この後関数型プログラミング言語の研究・開発は広まることとなった。1985年にMirandaが登場した。1987年に、遅延評価の純粋関数型プログラミング言語の標準の必要性が認識されHaskellの策定が始まった。1990年にHaskell 1.0仕様がリリースされた。同じく1990年にはMLの標準であるStandard MLもリリースされている。

Cleanは1987年に登場したが、発展の過程でHaskellの影響を受けている。1996年に、ML処理系のひとつであったCamlオブジェクト指向を追加したOCamlが登場した。また日本ではSMLに独自の拡張を施したSML#が開発されている。

21世紀に入ると、Java仮想マシン共通言語基盤CLI)をランタイムとする関数型プログラミング言語を実装しようという動きが現れ、ScalaClojureF#などが登場した。

関数型プログラミング言語一覧

言語 純粋さ 型付け
Clean 純粋 強い、静的
Clojure 非純粋 動的
Erlang 非純粋 動的
F# 非純粋 強い、静的
Haskell 純粋 強い、静的
Idris 純粋 強い、静的
Lazy K 純粋 型なし
LISP 非純粋 動的
Miranda 純粋 強い、静的
ML 非純粋 強い、静的
SML# 非純粋 強い、静的
Standard ML 非純粋 強い、静的
OCaml 非純粋 強い、静的
Scala 非純粋 強い、静的
Scheme 非純粋 動的
Unlambda 非純粋 型なし

従来の手続き型と分類されるプログラミング言語においても、関数型プログラミングを行ないやすくなる機能を備えているものもある。C言語およびC++関数へのポインタをサポートし、関数をオブジェクトのように扱うことができるが、関数ポインタによって第一級関数をサポートしているとみなされてはいない。なお、C# 3.0、C++11、Java 8など、後発の規格においてラムダ式(無名関数)をサポートするようになった言語もある。

その他の関数型プログラミング的性質を持つ言語

外部リンク

参考文献

  1. ^ 共立出版ANSI C/C++辞典』ISBN 4-320-02797-3 など
  2. ^ 関数型プログラミングのエッセンスとして、MISRA CのようにC言語でも副作用を極力用いないプログラミングを推奨しているコーディング標準もある。
  3. ^ Oleg Kiselyov, Ralf Lämmel. “Haskell's overlooked object system”. 2005年9月10日閲覧。
  4. ^ 「プログラミングはフォン・ノイマン・スタイルから解放されうるか?: 関数型プログラミング・スタイルとそのプログラム代数」、米澤明憲訳『ACMチューリング賞講演集』(共立出版)pp. 83-156