高階関数は関数をファーストクラスオブジェクトとして扱うことの出来る ( $\Leftrightarrow$ 第一級関数をサポートしている) プログラミング言語において定義されます.
Haskell のような関数型言語でなくとも, JavaScript, PHP, Ruby などは第一級関数をサポートしています.
ファーストクラスオブジェクト (第一級オブジェクトとも言う) とは, 生成, 代入, 演算, (引数・戻り値としての) 受け渡しといったその言語における基本的な操作を制限なしに使用できる対象のことです.

高階関数の定義

高階関数の定義を示します:

関数を引数にする関数、あるいは関数を戻り値とする関数のこと.

あくまで, 高階関数は第一級関数をサポートしているプログラミング言語においてだけ実現できる関数です.

関数を戻り値とする高階関数は, 数学の多変数関数と同様なものです.
多変数関数と対応付ければ, 高階関数がプログラミングで使うことが出来れば, 何かと便利そうだということがすぐに理解できると思います.

カリー化関数

カリー化関数は関数を戻り値とする高階関数の一種です。
以下のような 2 入力 1 出力の処理 ${\rm max}$ を考えます:

\begin{eqnarray*}
{\rm max}(x, y) \Colon x,\ y\ のうち大きい方を返す
\end{eqnarray*}

この処理 ${\rm max}$ を実現する 2 つの引数を取る関数を max とします.
このとき, 常に max(x, y) = cmax(x)(y) が成立する 1 つの引数を取る関数 cmaxmax のカリー化関数と呼びます.

関数 cmax の引数に x を渡して得られる関数 cmax(x) は 1 つの引数を取り, x と比べて大きい方を返す関数です.

カリー化は以下のように定義できます:

関数 $f$ の処理を $a$ とする. このとき以下のような関数を作る操作を考える:

\begin{eqnarray*}
 引数 \ &:&\ 関数\ f\ の最初の引数 \\
 戻り値 \ &:&\ 残りの引数を取り, 処理\ a\ と同じ出力を戻り値とする関数
\end{eqnarray*}

この操作を繰り返し, 処理 $a$ を「一引数を取る関数の合成」で実現することをカリー化と呼ぶ.
関数 $f$ が唯一の引数を取り, その引数が配列のような構造体である場合においては, その構造体の要素を引数と呼べばこの定義に当てはまる.

JavaScript で実際にカリー化関数を作ってみます.
以下のような 3 つの引数の掛け算の結果を返す関数を考えます.

function f(x, y, z) {
    return x * y * z;
}

この関数の「最初の引数」を引数とし, 戻り値が「残りの引数を取り同じ結果を返す関数」を作ります:

function cf(x) {
    return function(y, z) {
        return x * y * z;
    }
}

これをもう一度繰り返す, すなわち, cf の戻り値の関数に対して同じ操作を繰り返すと, 以下のカリー化関数が得られます:

function ccf(x) {
    return function(y) {
        return function(z) {
            return x * y * z;
        }
    }
}

一引数を取る関数の合成になっています.
これらの関数の形式 (型) は以下のように表されます:

\begin{eqnarray*}
f &\Colon& X \times Y \times Z \to \RR \\
cf &\Colon& X \to (Y \times Z \to \RR) \\
ccf &\Colon& X \to (Y \to (Z \to \RR))
\end{eqnarray*}

丸括弧は省略されることがあります. 丸括弧は関数になっています. 例えば, $ccf$ に 1 つの引数を渡すと $Y \to (Z \to \RR)$ という型の関数を返すことを意味しています. そしてこれは, この関数に 1 つの引数を渡すと $Z \to \RR$ という型の関数を返すことを意味しています. さらにこれは, この関数に 1 つの引数を渡すと $\RR$ という型の値, すなわち, 実数値が得られることを意味しています.

以下の 3 つの式は全て同値です:

f(2, 3, 4);
cf(2)(3, 4);
ccf(2)(3)(4);

上の 3 つの関数は全て同じ処理内容ですが, 特にカリー化関数 ccf は柔軟な使い回しが可能です:

var cf2 = cf(2);
var ccf2 = ccf(2);
var ccf6 = ccf(1)(6);

cf2(3, 4);  // 24
ccf2(3)(4); // 24
ccf6(10);   // 60

このように高階関数の一部の引数を固定し, 新たな関数を得る操作を部分適用と呼び, 得られる関数を部分適用関数と呼びます.
部分適用関数 cf2, ccf2, ccf6 の型は以下のように書けます:

\begin{eqnarray*}
cf2 &\Colon& Y \times Z \to \RR \\
ccf2 &\Colon& Y \to (Z \to \RR) \\
ccf6 &\Colon& Z \to \RR \\
\end{eqnarray*}

関数型言語では複数の引数を受け付ける関数は, 実際は全て 1 つの引数の関数です. すなわち, 全ての関数は通常の意味でのカリー化された関数です. このような言語においては, 引数が「複数の要素をもつ構造体」の場合, それらの要素を引数とした「一引数を取る関数の合成」にすることをカリー化と呼びます.

Haskell で同じ関数は f x y z = x * y * z とすると作成できます. f 2 は上の $ccf2$ と同じ関数になります. 実際, 型を調べると,

Prelude> let f x y z = x * y * z
Prelude> :t f
f :: Num a => a -> a -> a -> a
Prelude> :t f 2
f 2 :: Num a => a -> a -> a
Prelude> :t f 2 3
f 2 3 :: Num a => a -> a

となります.

参考