web-dev-qa-db-ja.com

実際のカレーと部分関数の適用の違いは何ですか

部分的な関数の適用とカリー化された関数の違い(f(X x Y x Z) -> N vs f(X -> (Y -> (Z -> N))))を理解していますが、ソフトウェアの開発時にこの違いの結果がどうなるかわかりません。

8
Henk

元々、カリー化は実用的なプログラミング手法ではなく、分析を単純化することでした。ラムダ計算では、すべての関数は単項です。カレーは、同様の理由で言語レベルでよく使用されます:計算モデルの単純化。

名前付きの便利な関数を、引数を修正するだけで、より一般的な別の関数として実装できる場合に、部分的なアプリケーションが使用されます。

それらは、計算のさまざまな部分を含む別個の形式のままです。検討してください:

x=>y=>z=>f(x,y)
(y,z)=>f(0,y,z)

カリー化された関数は引数にバインドされた値を持たず、特定の順序で引数を取ります。関数をカレー化すると、結果をカレー化したり、関数が引数をとる順序を変更したりすることはありません(ただし、カレー化してカレー化することはできます)。対照的に、部分関数には引数にバインドされた値があり、残りの引数に沿ってさらに部分的に適用できます。

カリー化された関数の適用は部分的な適用に近い(結局のところ、関数をカリー化せずにそのままにしておきます。ある時点で適用することになります)。これは用途が交差し始める場所です。これを行う場合、カレーは、部分的な適用に向けた2つのステップのうちの最初のステップにすぎません。

5
outis

あなたの質問は次のように言い換えることができると思います:なぜ言語はカレーを持っているのですか?

それは主に利便性の問題です:

Ocamlでは、

 let sum3 x y z = x + y + z;;
 let foo xx yy ll = List.map (sum3 xx yy) ll;;

Schemeでは、無名関数を明示的に作成する必要があります

 (define (sum3 x y z) (+ x y z))
 (define (foo xx yy ll) (map (lambda (zz) (sum3 xx yy zz)) ll))  

部分的なアプリケーションとカリー化を伴う言語では、あらゆる場所で部分的なクロージャーを作成しないように、最適化を行う必要があります。実装を望まないalways適用sum3のように定義されているかのように

 let sum3 x = 
    fun y -> 
      (fun z -> x + y + z)

つまり、sum3 1 2 3((sum3 1) 2) 3 ...として理解および解析される)の計算時に2つの中間クロージャーを割り当てることです。合計をすぐに計算する必要があります。