関数型プログラミングの基本
informationprogramming-languageslecture
data/lecture/information/programming/introduction-to-programming.lecture.n.md
1導入
この講義では、関数の適用と式の評価を中心に計算を構成する関数型プログラミングを説明する。純粋関数、不変性、高階関数、参照透過性を定義し、これらが局所的な推論に寄与する理由を解説する。
関数型と命令型は、相互排他的な分類ではない。現実の言語は両者の機能を併用することが多く、問題に応じて状態更新と純粋な計算を適切に配置することが重要である。
2基本用語
純粋関数とは、返値が引数だけによって決定され、評価によって外部から観察可能な状態変化を生じさせない関数である。
副作用とは、返値の計算とは別に発生する、外部から観察可能な変化である。共有変数の更新、入出力、例外の送出などが該当する。
不変性とは、値を生成した後にその内容を変更しない性質である。変更後の情報が必要な場合は、既存の値を改変せずに新しい値を生成する。
第一級関数とは、他の値と同様に、引数、返値、データ構造の要素などとして扱える関数値である。高階関数とは、関数を引数として受け取るか、関数を返値として返す関数である。
参照透過性とは、ある式を、その式の値で置換してもプログラムの観察可能な振舞いが変化しない性質である。
3純粋関数と不変性
たとえば、整数を 1 増加させる純粋関数は次のように記述できる。
increment(3) は評価するたびに 4 となり、その評価は共有状態を変更しない。これに対して、共有カウンタを更新してから返す関数は、そのカウンタの現在値に結果が依存するため、純粋関数ではない。
不変なリスト xs の先頭に x を追加する操作は、xs を変更せず、x と xs から新しいリストを構成する。旧リストを参照する他の式の意味は、この操作によって変化しない。
4参照透過性と等式推論
式 e が値 v に評価され、e が参照透過的であるとする。このとき、プログラム内の e を v で置換しても観察結果は変化しない。この性質により、式の変形を等式として検証する等式推論が可能になる。
ただし、入出力そのものが不要になるわけではない。関数型言語は、効果を明示する型や構文、または純粋な計算と効果を伴う境界の分離によって、必要な入出力を扱う。
5高階関数
map(f, []) = []
map(f, x :: xs) = f(x) :: map(f, xs)
map は関数 f を引数として受け取るため、高階関数である。リストの走査方法を map に集約し、各要素への処理を f として分離できる。この分離は処理の再利用と合成を促進する。
6命令型との関係
命令型プログラミングは、代入などの命令による状態遷移を中心に記述する。関数型プログラミングは、式の評価と関数適用を中心に記述する。この相違は記述の重点にあり、どちらか一方だけが常に適切であることを意味しない。
たとえば、呼出しごとに局所的な可変配列を使用し、その参照を外部へ漏洩させず、呼出履歴が観察結果へ影響しないなら、外部には純粋な関数として提示できる。
7要点
- 純粋関数は返値を引数だけから決定し、観察可能な副作用を生じさせない。
- 不変性と参照透過性は、式を局所的に推論するための基盤となる。
- 高階関数は、計算の共通構造と個別処理を分離する。
- 実用的なプログラムでは、純粋な計算と必要な効果を明確な境界で統合する。
8次に進む講義
data/lecture/information/programming-languages/foundation/variable-binding-and-free-variables-basics.lecture.n.md