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

削除された内容 追加された内容
Slappi (会話 | 投稿記録)
(同じ利用者による、間の3版が非表示)
2行目:
{{プログラミング言語|index=かんすうかたけんこ}}
[[ファイル:Orange_lambda.svg|代替文=|境界|右|フレームなし|167x167ピクセル]]
'''関数型言語'''({{lang-en-short|''functional language''}})は、'''関数型プログラミング'''スタイルまたは[[プログラミングパラダイム|パラダイム]]を扱う[[プログラミング言語]]の総称である。'''純粋関数型'''(''purely functional'')プログラミングは関数の[[写像|適用]]'''非純粋[[関数型'''(''impure functional'')二つに大別され、後者の方が幅広く用い合成|合成]]から組み立てられてい[[マルチパラダイム宣言型プログラミング言語|マルチパラダイム言語]]に組み込まれているもは例外なく非純粋一種である。り、関数は[[引数]]の適用から先行式の[[評価戦略|評価]]を後続式の適用に順次ないし再帰的に繋げて終端評価に到る[[式 (プログラミング)|式]]の[[木文(''syntax'')造 (データ構造)|ツリー構造]]設計(''design'')の二つの視点から解釈して定義される。構文スタイルと設計原則の双方に忠実なのが純粋関数型である。構文面を中心に導入し設計面にそれほど忠実で引数ないか又はほし返値んど度外視して渡せのが非純粋[[第一級関数型であ]]として扱われる。
 
関数型プログラミングは[[数理論理学]]と[[圏論]]を主にした数学分野をルーツにし、関数[[形式体系]]の[[ラムダ計算]]と[[コンビネータ論理]]を幹にして構築され、[[LISP]]言語が実装面の先例になっている。関数の数学的な純粋性を追求した純粋関数型言語も存在する。純粋関数型パラダイムでは[[参照透過性]]が最重視され[[モナド (プログラミング)|モナド]]などの特別な[[型システム]]が導入されている。また[[並行計算]]パラダイムでは純粋関数が重視されている。関数型プログラミングと標榜される言語の多くは組込みスタイルとしてそれを扱っている。[[高階関数]]と[[第一級関数]]、[[クロージャ]]または[[無名関数]]、関数合成と部分適用、ポイントフリーまたは[[パイプライン処理|パイプライン]]、[[イテレータ|イテレーション]]またはリスト処理、[[型推論]]、[[多態性|パラメータ多相]]、[[パターンマッチング]]、[[再帰]]の最適化、[[演算子オーバーロード]]、[[イミュータブル]]定義などが関数型のスタイル要素として挙げられる。
== 特徴 - 構文面 ==
 
[[ラムダ計算]]と[[コンビネータ論理]]と[[LISP]]言語が土台になっている。
== 特徴 - 構文面 ==
ここでは関数型プログラミング本来の構文スタイルを元にして説明する。式を基本文にする関数型に対して、[[文 (プログラミング)|ステートメント]]を基本文にする[[手続き型プログラミング|手続き型]]や[[オブジェクト指向プログラミング|オブジェクト指向]]などの[[命令型プログラミング]]言語では必要に応じて構文スタイルが改変されている。代表的なのは「式の引数への適用」に対する「引数を関数に渡す」である。ただし双方ともアセンブリコード上では同様に符号化される。[[代数的データ型]]は[[構造体]]や[[連結リスト]]で置き換えられ、単体値ないし[[プリミティブ型|プリミティブ値]]では用いられないのが大半である。
 
=== 式と関数 ===
 
*関数型プログラムの[[文 (プログラミング)|基本文]]は[[式 (プログラミング)|式]](''expression'')である。式は値と同一視される。
*式は、値(''value'')と演算子(''operator'')と関数(''function'')で構成される。式内の代数部分が確定される前の式は抽象値と同義であり、確定後の式は実値と同義になる。ここでの代数とは式内の各束縛変数と、同じく式内の各関数の引数の双方を指す。実値の導出過程は評価(''evaluation'')と呼ばれる。
*式を評価した値の後続式への反映は変数への代入ではなく、[[束縛変数]]で定数化するのが本来の在り方である。
*{{要出典範囲|{{仮リンク|暗黙プログラミング|en|tacit programming|label=}}が指向されており、直前の引数値または先行式の評価値はそのまま直をデフォルトで式の適用値と見なして値の記述を省略する事もでき構文が多用される。これは[[パイプライン処理|パイプライン]]またはポイントフリーと呼ばれる|date=2020年5月}}
*関数も値と同一視される。関数は引数(''parameter'')と式を結び付けるユニットである。式の代数部分に引数値が順次束縛される。も値なツリーで関数のフロー終端式がそのまま評価値になる。
*関数は、式の引数への適用(''application'')と解釈される。{{要出典範囲|その対義概念として反適用(''unapplication'')の仕組みも存在する。これは式の引数への適用を差し戻して元の引数を抽出する|date=2020年5月}}。
*関数は、式を第1引数に適用したもの→第2引数に適用したもの→第x引数に適用したもの→評価値、というようなをとになのが標準で、これは[[カリー化]]。LISPなど、例外もあと呼ばれ。関数の型は各引数値から評価値までの型の連鎖として表現され、これはカインド(''kind'')とも呼ばれる。
*2個以上の引数を同時適用する非カリー化の関数も用いられる。無名関数がしばしばそれになる。この場合は部分適用やポイントフリーが制限される。
*型の連鎖は、さながらパズルのような関数の断片化と連結を可能にする。前者は部分適用と呼ばれ、例えば式を第1引数に適用しただけのものを後続の式で使い回せる。後者は関数合成と呼ばれ、評価値と第1引数が同じ型の関数をつなげたものを後続の式で使い回せる。
*関数は名前付きと名前無しの二通りある。後者はラムダ抽象を模した構文で式中に直接定義される。これは[[クロージャ]]または[[無名関数]]と呼ばれる。
*関数は値と同義なので、関数の引数値を関数にする事も可能であり、また関数の評価値を関数にする事も可能である。他の関数を引数値または評価値として扱える関数は[[高階関数]]と呼ばれる。他の関数から引数値または評価値として扱われる関数は[[第一級関数]]と呼ばれる。
*演算子は、デフォルトの式内容を持ち引数が1~2個に限定された関数と同義である。演算子の式内容は一部の例外を除いて任意に再定義できる(例外もある。)。部分適用された演算子はセクションと呼ばれる第一級関数になる。
 
=== 代数的データと値 ===
{{Cn|date=2020年5月}}
*値(''value'')は型(''type'')によって分類される。
*値は代数的データ(''algebraic data'')として表現される。代数的データは、''atom(プリミティブ)nil(無)cons(値+リンク)''の要素からなる。代数的データは''cons''の再帰で構成されており、ゼロ個から複数以上の値を内包する事になる。''cons''の値は''atom''または入れ子の代数的データを指し、''cons''のリンクは次の''cons''または''nil''を指す。''atom''は数値、論理値、文字、文字列を指す。この再帰ツリー構造は[[S式]]と呼ばれる。
*代数的データは単体値の表現でもあり、あらゆる値集合の原始的表現でもある。代数的データによって単値と値集合を同等に扱うスタイルが関数型プログラミングの代表的利点であるリスト処理([[イテレーション]])に繋がっている。
*代数的データは''cons''の再帰構造であり、先頭''cons''の値+リンクを常時分離表現できる。そのリンクは後続全''consを''表現する。そのリンクが指す''cons''を再帰関数の引数にして値+リンクを再度分離しそのまた再帰を繰り返していくと、結果的に代数的データの全内包値に作用を及ぼせる事になる。
*全ての値が同じ型の代数的データは''list''と呼ばれ、異なる場合は''tuple''と呼ばれる。''list''は用法的に[[線形リスト]]と同義であり、''tupleは用法によっては''[[構造体]]の近似物になる。
 
*値(''value'')は代数的データ型(''algebraic data type'')として表現される。これ[[直積]]、[[非交和]]、[[再帰]]の構造を持ち、単体値の表現でもあり、を兼ねたあらゆる値集合の原始的汎用表現でもあになる。代数的データによって単値と値集合を同等に扱うスタイルが関数型プログラミングの代表的利点であるリスト処理([[イテレータ|イテレーション]])に繋がっている。
=== 再帰と分岐 ===
*値は代数的データ(''algebraic data'')として表現される。代数的データは、''atom(プリミティブ)nil(無)cons(内包値+リンク)''の要素からなで実装される。代数的データは''consatom''の再帰で構成されており、ゼロ個から複以上の、論理値、文字、文字列内包る事になる。''cons''の''内包''は''atom''または次の''cons(=''入れ子の代数的データを指し、''cons''のリンクは次の''cons''または''nil''(=終端)を指す。代数的データは''atomcons''の再帰で構成されてゼロ個から複以上の、論理値、文字、文字列内包る事になる。この再帰ツリー構造は[[S式]]と呼ばれる。
*値(''value'')は型(''type'')によって分類される。
*全ての値が同じ型の代数的データは''list''と呼ばれ、異なる場合は''tuple''と呼ばれる。''list''は用法的に[[線形リスト]]と同義であり、''tupleは用法によっては''[[構造体]]の近似物になる。この双方は前述の[[直積]]である。
*型選択している代数的データは''variants''などと呼ばれ、[[共用体]]ないし[[列挙型]]の類似物になる。これは前述の[[非交和]]である。
*前述の再帰は代数的データの[[ネスティング|入れ子構造]]を表現し、その入れ子はパラメータ多相で[[総称型]]にできる。
*値の型宣言と型指定は積極的に省略される。省略された型を自動的に導き出す機能は[[型推論]]と呼ばれる。型推論と[[多態性|パラメータ多相]]はよく併用される。
 
=== 再帰と非正格評価とパターンマッチング ===
 
*[[再帰]]が重視されている。関数の再帰呼び出しと[[相互再帰]]が多用される。データ定義でも、データ名に対する定義式の中で自身データ名が記述される再帰定義が多用される。
*カウンタ変数を増減するループ文は用いられないのが本来の在り方である。同様の反復フローはカウンタ値を引数にした関数の再帰で行う。
*引数値による多分岐節([[パターンマッチング]])が多用される。関数型プログラミングにおける選択フローは、引数の多分岐から始まる関数に集約される。
 
== 特徴 - 設計面 ==
[[数理論理学]]と[[数学基礎論]]と[[圏論]]が土台になっている。ただし専門性の強いプログラムを除くと、それらの参考は大まかなものである。
 
=== パラダイム ===
関数型プログラミングは[[宣言型プログラミング]]のカテゴリに属している。宣言型と対照的関係にあるのが[[命令型プログラミング]]であり、そのカテゴリには[[手続き型プログラミング|手続き型]]や[[オブジェクト指向プログラミング|オブジェクト指向]]が属している。この両者を分ける一つの基準は[[副作用 (プログラム)|副作用]](''side-effect'')に対する扱い方である。副作用とは、現行プロセスの閉包領域の外にある様々な情報資源の状態である「環境」の変化と、その変化によって各プロセスの処理過程もまた影響を受ける事を指す。ここでの情報資源とは、プログラムの各種入出力を担う[[オペレーティングシステム|OS]]の現行状態と、プログラムを走行させている[[仮想マシン|ランタイム環境]]が提供する各種データリソースを意味する。命令型プログラミングは前述の「環境」に対して自由に作用を及ぼせるパラダイムであり、それが”''imperative''”の由来にもなっている。それに対して宣言型プログラミングは作用を及ぼせる対象と、自身がその影響を受ける事になる対象が、あらかじめ初期値または入力値として”''declarative''”された情報資源のみに限られている。加えて関数型プログラミングは原則的に、宣言されたデータに対しても作用を及ぼさず、他の値を導き出す為の因子として扱う。
 
=== 参照透過性 ===
純粋関数型プログラミングの世界言語[[参照透過性]]の原則下遵守をプログラムの枠組みしている。参照透過性の意味自体は非常にシンプルであり、関数は同じ引数値に対して必ず同じ評価値を恒久的に導出し、その評価過程においてプログラムの認知内における一切の情報資源に作用を及ぼさない、というものである。プログラムが認知する範囲内のいずれかの情報資源が変化するのと同時にいずれかの関数の評価過程も変化してしまう現象が[[副作用 (プログラム)|副作用]]と呼ばれる。
 
=== 型システム ===
 
=== 純粋関数とイミュータブルと並行計算 ===
=== 再帰と評価戦略 ===
 
=== 純粋関数と並行計算 ===
 
== 歴史 ==