私はまだカレーについて少し混乱しています -
SML で map を実装していますが、これはカリー化された関数と見なされますか?
fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
または、単一のパラメーターの受け渡しを強制することについて、より明確にする必要がありますか?
fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
私はまだカレーについて少し混乱しています -
SML で map を実装していますが、これはカリー化された関数と見なされますか?
fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
または、単一のパラメーターの受け渡しを強制することについて、より明確にする必要がありますか?
fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
はい、両方の関数がカリー化されています。実際、最初の関数は 2 番目の関数の省略形です。
アダムはすでにこれに答えましたが、私はあなたに釣りを教えたいと思います。
関数を SML インタープリターに入力するたびに、関数の型シグネチャを含む応答が返されます。これが最初のものです:
- fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
val mymap = fn : ('a -> 'b) -> 'a list -> 'b list
そして、これが2番目のものです:
- fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
val mymap = fn : ('a -> 'b) -> 'a list -> 'b list
最初に気付くのは、それらが同じ型シグネチャを持っていることです。これは、2 番目が最初の脱糖形式であるという主張と一致しています。
署名によると、mymap
ある型から別の型にマップする関数を受け取ります。を使って実験してみましょうInt.toString
:
- mymap Int.toString;
val it = fn : int list -> string list
関数の部分的な適用を行ったところです。これは、カリー化された関数mymap
であるためにのみ可能です。mymap
mymap
対照的に、カリー化されていないのバージョンで何が起こるか見てみましょう。
- fun mymapUncurried (f,xs) = List.foldr (fn (x, l) => (f x)::l) [] xs;
val mymapUncurried = fn : ('a -> 'b) * 'a list -> 'b list
これは、引数がタプルで囲まれていることを除いて、最初の関数と同じです。その結果、型シグネチャも異なります ( *
? を参照)。 は、最初の要素が typeで、2 番目の引数が type である 2mymapUncurried
タプルを取ります。部分適用が機能しなくなりました。('a -> 'b)
'a list
- mymapUncurried Int.toString;
stdIn:9.1-9.28 Error: operator and operand don't agree [tycon mismatch]
operator domain: ('Z -> 'Y) * 'Z list
operand: int -> string
in expression:
mymapUncurried Int.toString
ただし、完全なアプリケーションは機能します。引数をタプルとして渡すことを忘れないでください。
- mymapUncurried (Int.toString, [1,2,3]);
val it = ["1","2","3"] : string list