インターネット上では、他の人のカリー化の例はカリー化ではなく、実際には部分的な適用に過ぎないというさまざまな苦情をよく見かけます。
部分適用とは何か、またそれがカリー化とどう違うのか、きちんとした説明が見つかりませんでした。全体的に混乱があるようで、同等の例が、ある場所ではカリー化として説明され、他の場所では部分適用として説明されています。
両方の用語の定義と、それらの違いの詳細を教えていただけますか?
ベストアンサー1
カリー化とは、 n 個の引数を持つ単一の関数を、それぞれ単一の引数を持つn個の関数に変換することです。次の関数があるとします。
function f(x,y,z) { z(x(y));}
カレー化すると次のようになります:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
f(x,y,z) を完全に適用するには、次のようにする必要があります。
f(x)(y)(z);
多くの関数型言語では、 と記述できます。またはf(x)(y)f x y z
のみを呼び出すと、部分的に適用された関数が得られます。戻り値は、x と y の値が に渡された のクロージャです。f x y
lambda(z){z(x(y))}
f(x,y)
部分適用を使用する 1 つの方法は、関数を foldのような一般化関数の部分適用として定義することです。
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10