「関数型プログラミング」の版間の差分
削除された内容 追加された内容
編集の要約なし |
|||
2行目:
{{プログラミング言語|index=かんすうかたけんこ}}
[[ファイル:Orange_lambda.svg|代替文=|境界|右|フレームなし|167x167ピクセル]]
'''関数型言語'''({{lang-en-short|''functional language''}})は、'''関数型プログラミング'''のスタイルまたは[[プログラミングパラダイム|パラダイム]]を扱う[[プログラミング言語]]の総称である。関数型プログラミングは関数の[[写像|適用]]と[[関数の合成|合成]]から組み立てられる[[宣言型プログラミング]]の一種であり、関数は[[引数]]の適用から先行式の[[評価戦略|評価]]を後続式の適用
関数型プログラミングは[[数理論理学]]と[[圏論]]を主にした数学分野をルーツにし、関数[[形式体系]]の[[ラムダ計算]]と[[コンビネータ論理]]を幹にして構築され、[[LISP]]言語が実装面の先例になっている。関数の数学的な純粋性を追求した純粋関数型言語も存在する。純粋関数型パラダイムでは[[参照透過性]]が最重視され[[モナド (プログラミング)|モナド]]などの特別な[[型システム]]が導入されている。また
== 特徴 ==
ここでは関数型プログラミング本来の構文スタイルを元にして説明する。式を基本文にする関数型に対して、[[文 (プログラミング)|ステートメント]]を基本文にする[[手続き型プログラミング|手続き型]]や[[オブジェクト指向プログラミング|オブジェクト指向]]などの[[命令型プログラミング]]言語では必要に応じて構文スタイル
=== 式と関数 ===
{{出典の明記|date=2020年5月6日 (水) 02:29 (UTC)|section=1}}
*関数型プログラムの基本文は[[式 (プログラミング)|式]](''expression'')である。式は
*式は、値(''value'')と演算子(''operator'')と関数(''function'')で構成される。式内の代数部分が確定される前の式は抽象値と同義であり、確定後の式は実値と同義になる。ここでの代数とは式内の各束縛変数と、同じく式内の各関数の引数の双方を指す。実値の導出過程は評価(''evaluation'')と呼ばれる。
*式
*{{要出典範囲|引数値または先行式の評価値をデフォルトで後続式の適用値と見なして値の記述を省略する構文が多用される|date=2020年5月}}。これは[[パイプライン処理|パイプライン]]またはポイントフリーと呼ばれる。
*関数も値と同一視される。関数は引数(''parameter'')と式を結び付けるユニットである。式の代数部分に引数値が順次束縛され、式ツリーの終端式が評価値になる。
*関数は、式の引数への適用(''application'')と解釈される。{{要出典範囲|その対義概念として反適用(''unapplication'')の仕組みも存在する。これは式の引数への適用を差し戻して元の引数を抽出する|date=2020年5月}}。
*関数は、式を第1引数に適用したもの→第2引数に適用したもの→第x引数に適用したもの→評価値、という形
*2個以上の引数を同時適用する非カリー化の関数も用いられる。無名関数がしばしばそれになる。この場合は部分適用やポイントフリーが制限される。
*
*関数は名前付きと名前無しの二通りある。後者はラムダ抽象を模した構文で式中に直接定義される。これは[[クロージャ]]または[[無名関数]]と呼ばれる。
*
*言語によるが、演算子はデフォルトの式内容を持ち、引数が1~2個に限定された関数と同義である。演算子の式内容は任意に再定義できる。部分適用された演算子はセクションと呼ばれる第一級関数になる。
=== 代数的データ型 ===
{{出典の明記|date=2020年5月6日 (水) 02:30 (UTC)|section=1}}
*値(''value'')は代数的データ型(''algebraic data type'')として表現される。これは[[直積集合|直積]]、[[非交和]]、[[再帰]]の構造を持ち、単体値を兼ねたあらゆる値集合の汎用表現になる。代数的データによって単体値と値集合を同等に扱うスタイルが関数型プログラミングの代表的利点であるリスト処理([[イテレータ|イテレーション]])に繋がっている。
*代数的データ型は、''atom(プリミティブ)nil(無)cons(内包値+リンク)''の要素で実装される。''atom''は数値、論理値、文字、文字列を指す。''cons''の''内包値''は''atom''または次の''cons(=''入れ子の代数的データ)を指し、''cons''のリンクは次の''cons''または''nil''(=終端)を指す。代数的データは''cons''の再帰で構成されてゼロ個から複数以上の値を内包する事になる。この再帰ツリー構造は[[S式]]と呼ばれる。
*値は型(''type'')によって分類される。
*全ての値が同じ型の代数的データは''list''と呼ばれ、異なる場合は''tuple''と呼ばれる。''list''は用法的に[[線形リスト]]と同義であり、''tupleは用法によっては''[[構造体]]の近似物になる。
*型選択している代数的データは''variants''などと呼ばれ、[[共用体]]ないし[[列挙型]]の類似物になる。これは前述の[[非交和]]である。
*前述の再帰は代数的データの[[ネスティング|入れ子構造]]を表現
*値の型宣言と型指定は積極的に省略される。省略された型を自動的に導き出す機能は[[型推論]]と呼ばれる。型推論と[[多態性|パラメータ多相]]はよく併用される。
=== 再帰と
*
*選択構造では関数の引数値による[[パターンマッチング]]が多用され
=== 参照透過性 ===
46行目:
== 歴史 ==
初の関数型プログラミング言語とされる「[[LISP]]」は、1950年代に[[マサチューセッツ工科大学]]の[[ジョン・マッカーシー]]によって開発された。数々の後発言語の手本にされた[[マルチパラダイムプログラミング言語|マルチパラダイム]]言語であるLISPは同時に、[[ラムダ計算]]を元にして再帰可能にデザインされた''function''を始めとする数々の関数型プログラミング的な特徴を備えていた。ラムダ計算は1930年代に[[アロンゾ・チャーチ]]によって発明された[[計算模型]]であり、1937年に[[チューリング完全]]である事が示されて、[[チューリングマシン]]と等価な計算[[形式体系]]である事が証明されている。この経緯からラムダ計算は後に関数型プログラミングの基底理論に位置付けられた。同じく1930年代にラムダ計算と並ぶ[[計算模型]]の[[コンビネータ論理]]を考案し、[[カリー化]]の語源にもなった[[ハスケル・カリー]]がいる。LISPは多くの派生言語を生んでいるが、その中でも「[[Scheme]]」「[[Clojure]]」「[[Dylan]]」「[[ジュリア|Julia]]」は関数型プログラミングとしての特徴をより強調した言語になっている。
現代的な関数型プログラミング言語の祖としてはアイディアが1966年に発表された{{lang|en|[[ISWIM]]}}が挙げられるが、1970年前後までは関数型プログラミング言語の歴史は{{lang|en|LISP}}の発展が主である。1970年代にプロジェクトが開始された{{仮リンク|ロジック・フォー・コンピュータブル・ファンクションズ|en|Logic for Computable Functions}}のための言語として[[ML (プログラミング言語)|ML]]が作られている。また{{lang|en|LISP}}において、変数のスコープに静的スコープを採用した{{lang|en|Scheme}}が誕生したのが1975年である。
1977年、{{lang|en|FORTRAN}}の設計と[[バッカス・ナウア記法]]の発明の業績でこの年の[[チューリング賞]]を受賞した[[ジョン・バッカス]]は、{{lang|en|''Can Programming Be Liberated From the von Neumann Style?: A Functional Style and Its Algebra of Programs''}}<ref>「プログラミングはフォン・ノイマン・スタイルから解放されうるか?: 関数型プログラミング・スタイルとそのプログラム代数」、[[米澤明憲]]訳『ACMチューリング賞講演集』([[共立出版]])pp. 83-156</ref>と題した受賞記念講演で関数型プログラミングの重要性を訴えた。講演では[[FP (プログラミング言語)|FP]]という関数型プログラミング言語の紹介もした(サブタイトルの後半の「プログラムの代数」はこれを指す)が、これは{{lang|en|[[APL]]}}(特に、[[高階関数]]の意味がある記号({{lang|en|APL}}の用語ではオペレーター([[作用素]])という))の影響を受けている。
バッカスの{{lang|en|FP}}は広く使用されることはなかったが、この後関数型プログラミング言語の研究・開発は広まることとなった。1985年に{{lang|en|[[Miranda]]}}が登場した。1987年に、遅延評価の純粋関数型プログラミング言語の標準の必要性が認識され{{lang|en|Haskell}}の策定が始まった。1990年に{{lang|en|Haskell}} 1.0仕様がリリースされた。同じく1990年には{{lang|en|ML}}の標準である{{lang|en|[[Standard ML]]}}もリリースされている。{{lang|en|Clean}}は1987年に登場したが、発展の過程で{{lang|en|Haskell}}の影響を受けている。1996年に、ML処理系のひとつであった{{lang|en|Caml}}に[[オブジェクト指向]]を追加した{{lang|en|OCaml}}が登場した。また日本ではSMLに独自の拡張を施した{{lang|en|[[SML#]]}}が開発されている。
21世紀に入ると、[[Java仮想マシン|{{lang|en|Java}}仮想マシン]]や[[共通言語基盤]]({{lang|en|CLI}})をランタイムとする関数型プログラミング言語を実装しようという動きが現れ、{{lang|en|[[Scala]]}}・{{lang|en|[[Clojure]]}}・{{lang|en|[[F Sharp|F#]]}}などが登場した。
|