「カレー」とは何ですか?


653

私はいくつかの記事やブログでカレー関数への言及を見てきましたが、良い説明(または少なくとも意味のあるもの)を見つけることができません。


12
[非数学者には役に立たないため、コメントとして残します。]デカルトの閉じたカテゴリの定義に従って、X-> X x AとXの間に(Aによって自然にパラメータ化された)補助的な固定ファミリがあります。-> X ^A。同型hom(X x A、Y)<-> hom(X、Y ^ A)はHaskellのcurryおよびuncurry関数です。ここで重要なことは、これらの同型があらかじめ固定されているため、言語に「組み込まれている」ということです。
Alexandre C.

3
そこ素敵なチュートリアルは、ここではHaskellでカリー化のためにあるlearnyouahaskell.com/higher-order-functions#curried-functions短いコメントつまりadd x y = x+y(カレー)に異なっているadd (x, y)=x+y(uncurried)
Jaider

回答:


872

カリー化とは、複数の引数を取る関数を、それぞれが1つの引数のみを取る一連の関数に分解することです。JavaScriptの例を次に示します。

function add (a, b) {
  return a + b;
}

add(3, 4); // returns 7

これは、aとbの2つの引数を取り、それらの合計を返す関数です。この関数をカレーします。

function add (a) {
  return function (b) {
    return a + b;
  }
}

これは、1つの引数aを取り、別の引数bを取り、その合計を返す関数を返す関数です。

add(3)(4);

var add3 = add(3);

add3(4);

最初のステートメントは、add(3、4)ステートメントと同様に7を返します。2番目のステートメントは、引数に3を追加するadd3という新しい関数を定義します。これは、一部の人々がクロージャーと呼ぶかもしれないものです。3番目のステートメントでは、add3演算を使用して3に4を加算し、結果として7を生成します。


236
実際的な意味では、このコンセプトをどのように使用できますか?
イチゴ

43
@Strawberry、たとえば[1, 2, 3, 4, 5]、任意の数値を掛けたい数値のリストがあるとします。Haskellでは、map (* 5) [1, 2, 3, 4, 5]リスト全体をで乗算して5、リストを生成するように書くことができます[5, 10, 15, 20, 25]
nyson 2013年

62
map関数の機能は理解できましたが、あなたが説明しようとしている点が理解できるかどうかわかりません。map関数はカレーの概念を表していると思いますか?
イチゴ

78
@Strawberryへの最初の引数mapは、1つの引数(リストからの要素)のみを取る関数でなければなりません。乗算-数学的概念として-は二項演算です。2つの引数を取ります。ただし、Haskellに*はカリー関数がありadd、この回答の2番目のバージョンと同様です。の結果(* 5)は、単一の引数を取り、それを5倍する関数であり、mapで使用できます。
ドバル2014年

26
@Strawberry Standard MLやHaskellのような関数型言語の良いところは、「無料」でカレーができることです。他の言語と同じように複数の引数を持つ関数を定義できます。ラムダをたくさん投入しなくても、カレーバージョンを自動的に取得できます。そのため、既存の関数から引数をあまり取らず、手間をかけずに他の関数に渡すのが簡単な新しい関数を作成できます。
Doval 2014年

125

関数の代数では、複数の引数(またはNタプルである同等の1つの引数)をとる関数の処理はやや洗練されていません。 1つの引数を取る関数が必要です。

では、自然に表現したいことにどう対処するのでしょうf(x,y)か?まあ、あなたはそれをf(x)(y)- と同等であると見なし、それをf(x)呼び出しg、関数であり、その関数をに適用しますy。つまり、1つの引数を取る関数しかありませんが、それらの関数の一部は他の関数を返します(これらも1つの引数を取ります;-)。

いつものように、ウィキペディアにはこれに関する素晴らしい要約エントリがあり、多くの便利なポインタ(おそらくお気に入りの言語に関するものを含む)と、やや厳密な数学的処理があります。


1
私は上記のものと同様のコメントをしていると思います-関数型言語が関数を単一の引数を取るように制限しているのを見たことがありません 私は間違っていますか?
エリックM

1
@hoohoo:関数型言語は通常、関数を単一の引数に制限しません。ただし、より低く、より数学的なレベルでは、引数を1つだけ取る関数を処理する方がはるかに簡単です。(例えば、ラムダ計算では、関数は一度に1つの引数しか取りません。)
Sam DeFabbia-Kane '30

1
OK。次に別の質問。次の説明は正しいですか?ラムダ計算は関数型プログラミングのモデルとして使用できますが、関数型プログラミングは必ずしもラムダ計算に適用されるわけではありません。
エリックM

7
ウィキペディアのページに記載されているように、ほとんどのFP言語はラムダ計算を(「定数」やデータ型を使用して)「装飾」または「拡張」するだけでなく、「適用」するだけではありません。ところで、例えばHaskellは「関数を単一の引数を取ることだけに制限しない」という印象を与えるものは何ですか?それは確かにありますが、それはカレーのおかげで無関係です。例div :: Integral a => a -> a -> a-複数の矢印に注意してください?「aをaにマッピングする関数にマップする」は、1つの読みです;-)。&cに(単一の)タプル引数を使用することもできますdivが、Haskellではこれは本当に慣用的ではありません。
Alex Martelli、

@Alex-Haskell&arg countについては、Haskellに多くの時間を費やしていませんが、それは数週間前のことです。ですから、それは簡単な間違いでした。
エリックM

101

具体的な例を次に示します。

オブジェクトに作用する重力を計算する関数があるとします。数式がわからない場合は、こちらで確認できます。この関数は、必要な3つのパラメーターを引数として受け取ります。

今、地球上にいるので、この惑星上のオブジェクトの力を計算したいだけです。関数型言語では、地球の質量を関数に渡し、部分的に評価することができます。返されるのは、引数を2つだけ取り、地球上の物体の重力を計算する別の関数です。これをカレーといいます。


2
好奇心としては、JavaScriptのプロトタイプライブラリーはかなり正確にあなたがここで説明した内容ない機能を「カレー」提供:prototypejs.org/api/function/curry
shuckster


7
これは私には部分的な適用のように聞こえます。私の理解では、カリー化を適用すると、単一の引数を持つ関数を作成し、それらを合成してより複雑な関数を形成できるということです。何か不足していますか?
ネオタピル2013

9
@neontapirは正しいです。シェイが言ったことはカレーではありません。部分塗布です。引数が3つの関数がカリー化されてf(1)として呼び出す場合、返されるのは引数が2つの関数ではありません。別の1つの引数の関数を返す1つの引数の関数が返されます。カリー化された関数には、1つの引数しか渡せません。PrototypeJSのカレー機能もカレーではありません。それは部分的なアプリケーションです。
MindJuice 2015年

いいえ(部分評価)およびいいえ(カレー)。これは部分適用と呼ばれます。それを可能にするにはカレーが必要です。
ネスは

47

カリー化は、関数に適用できる変換であり、以前よりも引数を1つ少なく取ることができます。

たとえば、F#では次のように関数を定義できます。

let f x y z = x + y + z

ここで、関数fはパラメーターx、y、zを受け取り、それらを合計します。

f 1 2 3

6を返します。

したがって、この定義から、fのカレー関数を定義できます。

let curry f = fun x -> f x

ここで、 'fun x-> fx'は、C#のx => f(x)と同等のラムダ関数です。この関数は、カレーしたい関数を入力し、単一の引数取り、最初の引数を入力引数に設定して指定された関数を返す関数を返します。

前の例を使用すると、fのカレーを取得できます。

let curryf = curry f

その後、次のことを実行できます。

let f1 = curryf 1

これは、f1 yz = 1 + y + zと同等の関数f1を提供します。これは、以下を実行できることを意味します。

f1 2 3

これは6を返します。

このプロセスは、以下のように定義できる「部分機能アプリケーション」と混同されることがよくあります。

let papply f x = f x

それを複数のパラメータに拡張できますが、つまり:-

let papply2 f x y = f x y
let papply3 f x y z = f x y z
etc.

部分的なアプリケーションは関数とパラメーターを受け取り、1つ以上のパラメーターを必要としない関数を返します。前の2つの例が示すように、標準のF#関数定義に直接実装されているため、前の結果を達成できます。

let f1 = f 1
f1 2 3

これは6の結果を返します。

結論として:-

カレーと部分関数の適用の違いは次のとおりです。

カリー化は、関数を受け取り、単一の引数を受け入れ、最初の引数をその引数に設定して、指定された関数を返す新しい関数を提供します。これにより、複数のパラメーターを持つ関数を一連の単一引数関数として表すことができます。例:-

let f x y z = x + y + z
let curryf = curry f
let f1 = curryf 1
let f2 = curryf 2
f1 2 3
6
f2 1 3
6

部分関数の適用はより直接的です-関数と1つ以上の引数を取り、最初のn個の引数が指定されたn個の引数に設定された関数を返します。例:-

let f x y z = x + y + z
let f1 = f 1
let f2 = f 2
f1 2 3
6
f2 1 3
6

では、C#のメソッドは、部分的に適用する前にカレー化する必要があるでしょうか。
cdmckay

「これにより、複数のパラメーターを持つ関数を一連の単一引数関数として表すことができます」-完璧です。おかげで
ファジィ分析

44

関数を使用して他の関数を作成する方法にもなります。

JavaScriptで:

let add = function(x){
  return function(y){ 
   return x + y
  };
};

次のように呼び出すことができます:

let addTen = add(10);

これが実行される10と、として渡されxます。

let add = function(10){
  return function(y){
    return 10 + y 
  };
};

つまり、この関数が返されます。

function(y) { return 10 + y };

だからあなたが呼び出すとき

 addTen();

あなたは本当に電話しています:

 function(y) { return 10 + y };

したがって、これを行う場合:

 addTen(4)

それは同じです:

function(4) { return 10 + 4} // 14

したがって、addTen()渡したものには常に10が加算されます。同様の関数を同じ方法で作成できます。

let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
let addSeventy = add(70)  // ... and so on...

明らかなフォローアップの質問ですが、なぜ地球上でそれをしたいのでしょうか?それは熱心な操作だったものを変えますx + y遅延して実行できる変換します。つまり、少なくとも2つのことを実行できます。1.負荷の高い操作をキャッシュします。

カレー関数が次のようになっているとします。

let doTheHardStuff = function(x) {
  let z = doSomethingComputationallyExpensive(x)
  return function (y){
    z + y
  }
}

この関数を1回呼び出してから、結果を渡して多くの場所で使用することができます。つまり、計算に負荷のかかる処理を1回だけ実行します。

let finishTheJob = doTheHardStuff(10)
finishTheJob(20)
finishTheJob(30)

同様の方法で抽象化を取得できます。


5
私がここで見た本質的に逐次的なプロセスの最良の段階的な説明、そしておそらくそのロットの中で最も優れた、最も説明的な答え。

4
@jonsilver私は反対のことを言いますが、良い説明ではありません。提起された例を説明するのは得意だと私は同意しますが、人々はデフォルトで「ええ完全に明確ですが、同じことを別の方法で行うことができるので、カレーは何が良いのでしょうか」と考える傾向があります。言い換えれば、カレーがどのように機能するかだけでなく、10を追加する他の方法と比較して、それが役に立たない些細な観察ではない理由を明らかにするのに十分なコンテキストまたは説明があればいいのですが。
ホイットニーランド

29

カリー化された関数は、最初の引数を受け入れ、2番目の引数を受け入れる関数を返すように書き換えられたいくつかの引数の関数です。これにより、いくつかの引数の関数に、初期引数の一部を部分的に適用できます。


5
「これにより、いくつかの引数の関数に、初期引数の一部を部分的に適用することができます。」-なぜそれが有益なのですか?
acarlon 2013

5
@acarlon関数は、1つ以上の引数を同じにして繰り返し呼び出されることがよくあります。たとえば、リストのリストに対してmap関数fを使用するxss場合は、次のようにできますmap (map f) xss
Jon Harrop、2013

1
ありがとうございます。私はもう少し読みました、そしてそれは所定の位置に落ちました。
acarlon 2013

4
私はこの答えがそれを素晴らしい簡潔な方法で正しく理解していると思います。「カリー化」とは、複数の引数の関数を取り、それぞれが単一の引数を取り、単一の引数の関数を返す、または最終的な関数の場合は実際の結果を返す、深刻な関数に変換するプロセスです。 。これは、言語によって自動的に行われるか、または他の言語でcurry()関数を呼び出してカリーバージョンを生成できます。パラメータでカリー化された関数を呼び出すことはカリー化されないことに注意してください。カレーはもう起こりました。
MindJuice 2015年

7

Pythonのおもちゃの例を次に示します。

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(Python以外のプログラマが気を散らすのを避けるために、+による連結を使用するだけです。)

追加する編集:

http://docs.python.org/library/functools.html?highlight=partial#functools.partialを参照してください。これは、Pythonがこれを実装する方法における部分オブジェクトと関数の違いも示しています。


私はこれを取得しません-あなたはこれを行います:>>> am_quote = curry(display_quote、 "Alex Martelli")しかし、次にこれを行います:>>> am_quote( "currying"、 "いつものように、ウィキペディアは素晴らしい要約を持っています。 .. ")したがって、2つの引数を持つ関数があります。カリー化すると、3つの異なる機能を作成できるように思えますか?
エリックM

パーシャルを使用して1つのパラメーターのみをカレー化し、2つの引数を持つ関数を生成しています。必要に応じて、am_quoteをさらにカレーして、特定の主題についてAlexだけを引用したものを作成できます。数学の背景は、パラメータが1つだけの関数で終わることに焦点を当てているかもしれませんが、このようなパラメータをいくつでも修正することは、一般的に(数学の観点から言えば)カリーと呼ばれます。
Anon

(ところで-'>>>'は、Pythonインタラクティブインタープリターのプロンプトであり、コードの一部ではありません。)
Anon

argsの説明に感謝します。Pythonインタープリターのプロンプトについて知っています。行を引用しようとしましたが、うまくいきませんでした;-)
Eric M

あなたのコメントの後、私はここでSOを含む他の参照を検索して見つけましたが、「カレー化」との違いについてです。私がよく知っている不正確な使用法の多くのインスタンスに対応する「部分的アプリケーション」。インスタンスを参照してください:stackoverflow.com/questions/218025/…–
Anon、

5

カリーとは、関数をcallable asからcallable as f(a, b, c)に変換することf(a)(b)(c)です。

それ以外の場合、カリー化とは、複数の引数をとる関数を、引数の一部をとる一連の関数に分解することです。

文字通り、カリー化は関数の変換です。ある方法から別の方法で呼び出します。JavaScriptでは、通常、元の関数を保持するラッパーを作成します。

カリー化は関数を呼び出しません。変身するだけです。

引数が2つの関数をカリー化するカリー関数を作ってみましょう。つまり、curry(f)2つの引数があるため、次のようにf(a, b)変換されます。f(a)(b)

function curry(f) { // curry(f) does the currying transform
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}

// usage
function sum(a, b) {
  return a + b;
}

let carriedSum = curry(sum);

alert( carriedSum(1)(2) ); // 3

ご覧のとおり、実装は一連のラッパーです。

  • の結果curry(func)はラッパーfunction(a)です。
  • のようsum(1)に呼び出されると、引数は字句解析環境に保存され、新しいラッパーが返されfunction(b)ます。
  • 次に、sum(1)(2)最終的にfunction(b)提供2を呼び出し、元の複数引数の合計に呼び出しを渡します。

4

あなたが理解しpartialているなら、あなたはそこに半分いる。のアイデアpartial、関数に引数を事前に適用し、残りの引数のみを必要とする新しい関数を返すことです。この新しい関数が呼び出されると、プリロードされた引数と、それに提供された引数が含まれます。

Clojure +では関数ですが、物事を明確にするために:

(defn add [a b] (+ a b))

このinc関数は、渡された数値に1を追加するだけであることに気づくかもしれません。

(inc 7) # => 8

それを使って自分で構築しましょうpartial

(def inc (partial add 1))

ここでは、の最初の引数に1が読み込まれた別の関数を返しますadd。As addは2つの引数を取るので、新しいinc関数はb引数のみを必要とします。1つはすでに部分的に適用されているため、以前のように2つの引数は必要ありません。したがってpartial、デフォルト値が事前に提供されている新しい関数を作成するためのツールです。そのため、関数型言語では、関数は一般的な引数から特定の引数へと引数を並べ替えます。これにより、他の関数を構築するためにそのような関数を再利用しやすくなります。

次に、その言語が内省的に理解できるほど賢く、add2つの引数が必要かどうか想像してみてください。バランスをとるのではなく、1つの引数を渡したときに、関数が引数を部分的に適用した場合は、後からもう1つの引数を提供するつもりであると理解して、引数を渡したとしたらどうでしょう。その後、inc明示的にを使用せずに定義できますpartial

(def inc (add 1)) #partial is implied

これは、一部の言語の動作方法です。関数をより大きな変換に構成したい場合に非常に役立ちます。これはトランスデューサーにつながります。


3

私はこの記事とそれが参照している記事がカレーをよりよく理解するのに役立つとわかりました:http : //blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

他の人が述べたように、それは1つのパラメータ関数を持つための単なる方法です。

これは、渡されるパラメーターの数を想定する必要がないので便利です。そのため、2つのパラメーター、3つのパラメーター、および4つのパラメーター関数は必要ありません。


3

他のすべての回答と同じように、カリー化は部分的に適用される関数の作成に役立ちます。JavaScriptは、自動カレーのネイティブサポートを提供していません。したがって、上記の例は実際のコーディングには役立たない場合があります。livescriptにはいくつかの優れた例があります(これは基本的にjsにコンパイルされます) http://livescript.net/

times = (x, y) --> x * y
times 2, 3       #=> 6 (normal use works as expected)
double = times 2
double 5         #=> 10

上記の例では、引数の数が少ない場合、livescriptは新しいカレー関数を生成します(double)


3

Curryはコードを簡略化できます。これは、これを使用する主な理由の1つです。カリー化とは、n個の引数を受け入れる関数を、1つの引数のみを受け入れるn個の関数に変換するプロセスです。

原則は、クロージャー(クロージャー)プロパティを使用して、渡された関数の引数を渡し、それらを別の関数に格納して戻り値として扱い、これらの関数がチェーンを形成し、最後の引数が渡されて完了します。操作。

これの利点は、一度に1つのパラメーターを処理することによってパラメーターの処理を単純化できることです。これにより、プログラムの柔軟性と可読性も向上します。これにより、プログラムが管理しやすくなります。また、コードを小さな部分に分割すると、再利用しやすくなります。

例えば:

function curryMinus(x) 
{
  return function(y) 
  {
    return x - y;
  }
}

var minus5 = curryMinus(1);
minus5(3);
minus5(5);

私もできます...

var minus7 = curryMinus(7);
minus7(3);
minus7(5);

これは、複雑なコードをきちんと作成し、非同期のメソッドを処理する場合などに非常に便利です。


2

カリー化された関数は、1つではなく複数の引数リストに適用されます。

これは、カレーではない通常の関数で、2つのIntパラメーターxとyを追加します。

scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3

これはカレー化された同様の関数です。2つのIntパラメータの1つのリストの代わりに、この関数をそれぞれ1つのIntパラメータの2つのリストに適用します。

scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Intscala> second(2)
res6: Int = 3
scala> curriedSum(1)(2)
res5: Int = 3

ここで起こっていることは、を呼び出すとcurriedSum、実際には2つの従来の関数呼び出しが連続して行われるということです。最初の関数呼び出しは、という名前の単一のIntパラメータを取りx、2番目の関数の関数値を返します。この2番目の関数はIntパラメータを取ります y

以下firstは、の最初の従来の関数呼び出しが何をするかを精神的に実行するという名前の関数curriedSumです。

scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)(Int) => Int

最初の関数に1を適用すると、つまり最初の関数を呼び出して1を渡すと、2番目の関数が生成されます。

scala> val second = first(1)
second: (Int) => Int = <function1>

2番目の関数に2を適用すると、結果が得られます。

scala> second(2)
res6: Int = 3

2

カリー化の例は、現時点でパラメーターの1つしか知らない関数がある場合です。

例えば:

func aFunction(str: String) {
    let callback = callback(str) // signature now is `NSData -> ()`
    performAsyncRequest(callback)
}

func callback(str: String, data: NSData) {
    // Callback code
}

func performAsyncRequest(callback: NSData -> ()) {
    // Async code that will call callback with NSData as parameter
}

ここでは、コールバックの2番目のパラメーターがわからないので、それをperformAsyncRequest(_:)関数に送信するために別のラムダ/クロージャーを作成する必要があります。


func callback自体を返しますか?これは@と呼ばれているcallback(str)ためlet callback = callback(str)、コールバックは単なる戻り値func callback
nikk wong

いいえ、func callback(_:data:)2つのパラメーターを受け入れます。ここではString、1つのみを指定しているため、次のパラメーター(NSData)をlet callback待機しています。これが、データが渡されるのを待機している別の関数である理由です
S2dent

2

以下は、n noを使用した関数カリー化のジェネリックおよび最短バージョンの例です。パラメータの。

const add = a => b => b ? add(a + b) : a; 

const add = a => b => b ? add(a + b) : a; 
console.log(add(1)(2)(3)(4)());


1

ここでは、C#でのカリー実装の簡単な説明を見つけることができます。コメントで、カレーがいかに役立つかを示しました。

public static class FuncExtensions {
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return x1 => x2 => func(x1, x2);
    }
}

//Usage
var add = new Func<int, int, int>((x, y) => x + y).Curry();
var func = add(1);

//Obtaining the next parameter here, calling later the func with next parameter.
//Or you can prepare some base calculations at the previous step and then
//use the result of those calculations when calling the func multiple times 
//with different input parameters.

int result = func(1);

1

カリー化は、Javaスクリプトの高次関数の1つです。

カリーは多くの引数の関数であり、最初の引数を取り、残りの引数を使用して値を返す関数を返すように書き換えられます。

混乱していますか?

例を見てみましょう、

function add(a,b)
    {
        return a+b;
    }
add(5,6);

これは次のカレー機能に似ています、

function add(a)
    {
        return function(b){
            return a+b;
        }
    }
var curryAdd = add(5);
curryAdd(6);

では、このコードは何を意味するのでしょうか?

もう一度定義を読んで、

カリー化は多くの引数の関数であり、最初の引数を取り、残りの引数を使用して値を返す関数を返すように書き換えられます。

それでも、混乱していますか?深く説明させてください!

この関数を呼び出すと、

var curryAdd = add(5);

それはあなたにこのような関数を返します、

curryAdd=function(y){return 5+y;}

したがって、これは高次関数と呼ばれます。つまり、ある関数を順番に呼び出すと別の関数が返され、これは高次関数の正確な定義です。これが、伝説のJavaスクリプトの最大の利点です。カレーに戻って、

この行は、2番目の引数をcurryAdd関数に渡します。

curryAdd(6);

その結果、

curryAdd=function(6){return 5+6;}
// Which results in 11

ここでカレーの使い方を理解してください。だから、利点に来て、

なぜカレーなのか?

コードの再利用性を利用しています。少ないコード、少ないエラー。あなたはそれがより少ないコードであるかどうか尋ねるかもしれませんか?

ECMAスクリプト6の新機能の矢印関数でそれを証明できます。

はい!ECMA 6は、矢印関数と呼ばれる素晴らしい機能を提供します。

function add(a)
    {
        return function(b){
            return a+b;
        }
    }

アロー関数の助けを借りて、上記の関数を次のように書くことができます、

x=>y=>x+y

かっこいい?

したがって、コードを減らし、バグを減らすことができます!!

これらの高次関数の助けを借りて、バグのないコードを簡単に開発できます。

挑戦します!

カレーとは何か理解できたでしょうか。説明が必要な場合は、こちらからコメントしてください。

ありがとう、良い一日を!


0

「ReasonMLでのカレー」の例があります。

let run = () => {
    Js.log("Curryed function: ");
    let sum = (x, y) => x + y;
    Printf.printf("sum(2, 3) : %d\n", sum(2, 3));
    let per2 = sum(2);
    Printf.printf("per2(3) : %d\n", per2(3));
  };
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.