コンピュータ科学において、純粋関数型プログラミングとは通常、すべての計算を数学関数の評価として扱うプログラミングパラダイム(コンピュータプログラムの構造と要素を構築するスタイル)を指します。
プログラムの状態と可変オブジェクトは通常、時間論理を用いてモデル化されます。これは、プログラム実行の各ステップにおけるプログラムの状態を表す明示的な変数として表現されます。変数状態は、状態変換関数の入力パラメータとして渡され、関数は更新された状態を戻り値の一部として返します。このスタイルは、プログラム式の参照透過性を損なうことなく状態変化を処理します。
純粋関数型プログラミングとは、関数型パラダイム内の関数が、グローバル状態やローカル状態に関係なく、引数のみに依存するようにすることを指します。純粋関数型サブルーチンは、そのスコープに含まれる状態変数によって表される状態変化のみを可視します。
純粋な関数型プログラミングと不純な関数型プログラミングの正確な違いは議論の的となっている。Sabryが提案する純粋性の定義は、すべての一般的な評価戦略(名前呼び出し、値呼び出し、必要呼び出し)が同じ結果を生成することであり、エラーや分岐を起こす戦略は無視される。[ 1 ]
プログラムは、第一級関数や高階関数などの関数型プログラミングの概念を使用している場合に、通常は関数型であると言われます。[ 2 ]ただし、第一級関数は、配列や可変セルを使用する入出力メソッドなど、命令型パラダイムの手法を使用する可能性があるため、純粋に関数型である必要はありません。可変セルは、副作用として状態を更新します。実際、関数型として挙げられる最も初期のプログラミング言語であるIPLとLisp [ 3 ] [ 4 ]は、Sabry の定義によればどちらも「不純な」関数型言語です。
純粋関数型プログラムで終了する各評価戦略は、同じ結果を返します。特に、即時評価と遅延評価は必ず同じ結果を返すため、プログラマーはプログラムの評価順序を考慮する必要がありません。ただし、同じプログラムの遅延評価が停止しても、即時評価が終了しない可能性は依然としてあります。この利点は、遅延評価をはるかに簡単に実装できることです。すべての式は(プログラムの状態に関係なく)いつでも同じ結果を返すため、必要に応じて評価を遅らせることができます。
純粋関数型言語では、計算間の依存関係はデータ依存性のみであり、計算は決定論的です。したがって、並列プログラミングを行うには、プログラマは並列で計算すべき部分を指定するだけでよく、ランタイムがタスクのプロセッサへの分散、同期と通信の管理、並列でのガベージコレクションなど、その他の詳細をすべて処理できます。このスタイルのプログラミングは、競合状態やデッドロックなどの一般的な問題を回避しますが、命令型言語よりも制御性は劣ります。[ 5 ]
高速化を確実にするためには、タスクの粒度を大きすぎず小さすぎないように慎重に選択する必要があります。理論的には、実行時プロファイリングとコンパイル時分析を使用して、並列処理を導入することでプログラムが高速化されるかどうかを判断し、純粋関数型プログラムを自動的に並列化することが可能になります。実際には、これはあまり成功しておらず、完全な自動並列化は実用的ではありません。[ 5 ]
純粋関数型データ構造は永続性を持つ。関数型プログラミングには永続性が必須であり、永続性がなければ同じ計算でも異なる結果が返される可能性がある。関数型プログラミングでは永続性のある非純粋関数型データ構造を使用できるが、純粋関数型プログラムではそのようなデータ構造は使用できない。
純粋関数型データ構造は、命令型データ構造とは異なる方法で表現されることが多い。[ 6 ]例えば、 定数時間でアクセスおよび更新できる配列は、ほとんどの命令型言語の基本要素であり、ハッシュテーブルやバイナリヒープなどの多くの命令型データ構造は配列に基づいている。配列は、純粋関数型実装が可能なマップやランダムアクセスリストに置き換えることができるが、アクセスおよび更新時間は対数的である。したがって、純粋関数型データ構造は非関数型言語でも使用できるが、特に永続性が不要な場合は、最も効率的なツールではない可能性がある。
一般的に、命令型プログラムを純粋関数型プログラムに変換するには、以前は変更可能だった構造体が、それらを更新する関数から明示的に返されるようにする必要があります。これは、ストアパッシングスタイルと呼ばれるプログラム構造です。
純粋関数型言語とは、純粋関数型プログラミングのみを許容する言語のことである。ただし、純粋関数型プログラムは、純粋関数型言語ではない言語でも記述することができる。