3

Standard MLでは、次の宣言の違いは何ですか(私はで始まる定義を省略しました=):

fun f x y;

fun f (x, y);

私が理解している限り、最初の引数は2つの引数を取り、2番目の引数はタプルを取ります。もしそうなら、それでも、一方を他方に対して使用することの(実際的な)意味は何ですか?どちらが最良のスタイルであるかについての1つの議論はできますか?仮定すると、実際にはタプル全体を使用する必要はありません。つまり、xyは別々に関連性があります。

4

1 に答える 1

5

はい、あなたが言ったように、最初は「2つの引数」を取り、2番目はタプルである1つの引数を取ります。ただし、実際に何が起こっているのかを理解するには、カリー化を理解する必要があります。ML では、すべての「関数」は 1 つの引数 (それ以上でもそれ以下でもありません) を取ります。

2 番目のケースでは、これは理解しやすく、タプルである 1 つの引数を取り、タプル内のもので何かを行い、結果を返します。最初のケースでは、1 つの引数を受け取り、別の引数を受け取り、結果を返す関数を返す関数を定義しています。

たとえば、これは 2 つintの を取り、 を返す関数であるとしますint。これら 2 つの関数の型を見ると、参考になります。2 番目の関数の型は です(int * int) -> int。つまり、タプルから int への関数です。最初の関数の型は ですint -> int -> int。これ->は右結合であるため、 として解析できますint -> (int -> int)。ご覧のとおり、int を取り、関数を返します。構文fun f x y = ...は、より冗長な構文糖衣ですval f = fn x => fn y => ...。この関数を適用すると、たとえばf 3 4、関数の適用は左結合なので、実際にはであり(f 3) 4、どのように機能するかを確認できます:fを受け取り、int別の int に適用される関数を返します。これがカレーの要点です。ML の構文は単純に実行を透過的にします。

カリー化バージョン(最初のバージョン)では、部分適用が可能です。つまり、関数は概念的には 2 つの引数を取りますが、その数の引数を与える必要はありません。では、f 3 4上記の (これは です(f 3) 4) を取得しf 3、それを に適用する代わりに、4それを保持して変数などに格納するとどうなるでしょうか? 「必要な数よりも少ない引数を関数に与える」ことで、残りの引数を取る関数を自動的に取得します。たとえば、 を実行すると、リスト内のfor eachmap (f 3) someListのリストが計算されます。複雑な構文を記述する必要はありません。f 3 xx

標準 ML では、ライブラリ関数はほとんどがカリー化されていない形式です。一方、OCaml と Haskell では、ほとんどがカリー化された形式です。(この質問を参照してください。) ただし、高階関数 (map や fold など) である SML ライブラリ関数は、関数の引数を別の (カリー化された) 引数で受け取る傾向があります。

于 2012-10-27T18:39:01.013 に答える