Caml は関数型言語です。関数は当然数学的な意味の関数としても使えますし、他のデータと同じように自由に扱うことも出来ます。例として deriv
関数を示します。この関数は浮動小数点関数を引数にとり、導関数の近似を返します。
#
let deriv f dx = function x -> (f(x +. dx) -. f(x)) /. dx;;
val deriv : (float -> float) -> float -> float -> float = <fun>
#
let sin' = deriv sin 1e-6;;
val sin' : float -> float = <fun>
#
sin' pi;;
- : float = -1.00000000014
関数の合成も定義出来ます。
#
let compose f g = function x -> f(g(x));;
val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
#
let cos2 = compose square cos;;
val cos2 : float -> float = <fun>
関数の引数として渡された関数は「汎関数」や「高階関数」と呼ばれます。高階関数は特にイテレータのような、データ構造上の汎用の操作を提供するのに有用です。たとえば、標準 Caml ライブラリに List.map
という関数がありますが、この関数は引数に与えられた関数を、すべてのリストの要素に適用し、その結果のリストを返します。
#
List.map (function n -> n * 2 + 1) [0;1;2;3;4];;
- : int list = [1; 3; 5; 7; 9]
List.map
や他のリスト、配列関連の高階関数は、使用頻度が高いので、既にライブラリとして定義されていますが、何も特別なことはしていません。
下に示すように簡単に定義することができるのです。
#
let rec map f l = match l with [] -> [] | hd :: tl -> f hd :: map f tl;;
val map : ('a -> 'b) -> 'a list -> 'b list = <fun>