関数型プログラミングのカリー化は、オブジェクト指向プログラミングのオーバーロードと同じですか?そうでない場合、なぜですか?(可能であれば例を使用して)
Tks
関数型プログラミングのカリー化は、オブジェクト指向プログラミングのオーバーロードと同じですか?そうでない場合、なぜですか?(可能であれば例を使用して)
Tks
いいえ、それらは完全に無関係であり、類似していません。
オーバーロードは、同じコードをさまざまなタイプで使用できるようにするための手法です。関数型プログラミングでは、(さまざまな形式の)ポリモーフィズムとして知られています。
ポリモーフィック関数:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
これは、任意のリストmap
で動作する関数です。Int
これは多態的です-ハッシュテーブルのツリーのリストとしてのリストでも同様に機能します。また、関数を引数として取る関数であるという点で高階関数です。
カリー化とは、 n個の引数の構造をとる関数を、それぞれが1つの引数をとる関数のチェーンに変換することです。
カレー言語では、引数の一部に任意の関数を適用して、残りの引数を受け取る関数を生成できます。部分的に適用される関数はクロージャです。
また、 CurryとSchonfinkelによって発明された変換を適用することにより、カレー化された関数をカレー化されていない関数に(またはその逆に)変換できます。
curry :: ((a, b) -> c) -> a -> b -> c
-- curry converts an uncurried function to a curried function.
uncurry :: (a -> b -> c) -> (a, b) -> c
-- uncurry converts a curried function to a function on pairs.
カリー化は関数型プログラミングに固有のものではなく、オーバーロードはオブジェクト指向プログラミングに固有のものではありません。
「カリー化」とは、残りの引数の関数を取得するために必要な数よりも少ない引数を渡すことができる関数の使用です。つまり、plus
2つの整数引数を取り、それらの合計を返す関数がある場合、単一の引数1
をに渡すことができplus
、結果は1を物に加算するための関数になります。
Haskellish構文(隣接による関数適用を使用):
plusOne = plusCurried 1
three = plusOne 2
four = plusCurried 2 2
five = plusUncurried 2 3
漠然とCish構文(括弧で関数適用を使用):
plusOne = plusCurried(1)
three = plusOne(2)
four = plusCurried(2)(2)
five = plusUncurried(2, 3)
plusCurried
これらの例の両方で、1つの引数でのみ呼び出されることがわかります。結果は、変数にバインドしてから別の引数で呼び出すことができるものになります。カリー化を関数型プログラミングの概念として考えている理由は、その構文ではカリー化が非常に自然になるため、構文が隣接して適用される関数型言語で最もよく使用されるためです。plusCurried
およびのアプリケーションplusUncurried
を定義four
し、five
Haskellish構文では、マージして完全に区別がつかなくなるため、すべての関数を常に完全にカレーすることができます(つまり、すべての関数を1つの引数の関数にするだけで、一部の関数だけが他の関数を返し、それをさらに多くの引数に適用できます。 )。括弧で囲まれた引数リストによるアプリケーションを使用したCish構文では、との定義はfour
完全five
に異なるため、とを区別する必要がplusCurried
ありplusUncurried
ます。また、今日のオブジェクト指向言語につながった命令型言語には、関数を変数にバインドしたり、他の関数に渡したりする機能がありませんでした(これはファーストクラスの関数を持つこととして知られています)。その機能がなければ、実際にできることは何もありません。すべての引数で呼び出す以外のカリー化された関数を使用するため、それらを使用しても意味がありません。今日のオブジェクト指向言語のいくつかは、まだファーストクラスの関数を持っていないか、最近それらを取得しただけです。
カリー化という用語は、複数の引数の関数を、単一の引数を取り、別の関数(単一の引数を取り、別の関数を返す場合があります...)を返す関数に変換するプロセスも指します。逆変換を行うプロセスに。
オーバーロードは完全に無関係な概念です。名前のオーバーロードとは、異なる特性(引数の型、引数の数、戻り型など)を持つ複数の定義を与えることを意味し、コンパイラーに、名前が表示されるコンテキストによる名前の指定された外観が意味する定義を解決させます。
これのかなり明白な例は、整数を追加するように定義できますplus
が、浮動小数点数を追加するために同じ名前plus
を使用することもでき、文字列、配列、リストなどを連結したり、ベクトルや行列を追加したりするために使用できる可能性があります。これらはすべて、言語の実装に関する限り、互いに関係のない非常に異なる実装を持っていますが、たまたま同じ名前を付けました。次に、コンパイラはplus stringA stringB
、文字列を呼び出すplus
(そして文字列を返す)必要があるのに対しplus intX intY
、整数を呼び出すplus
(そして整数を返す)必要があるかどうかを判断する責任があります。
繰り返しますが、この概念が関数型プログラミングの概念ではなく「オブジェクト指向の概念」であるという固有の理由はありません。たまたま、開発された静的に型付けされたオブジェクト指向言語に非常に自然に適合しました。メソッドが呼び出されるオブジェクトによって呼び出すメソッドをすでに解決している場合は、より一般的なオーバーロードを可能にするための小さなストレッチです。完全にアドホックなオーバーロード(同じ名前を複数回定義し、コンパイラがそれを理解することを信頼するだけです)は、オーバーロードされた名前をあなたがしない機能自体オーバーロードされた定義)。Haskellは、オーバーロードを使用するより原理的な方法として型クラスを開発しました。これらは事実上、オーバーロードされたすべての定義を一度に渡すことを可能にし、型システムが「関数f
とg
が定義されている任意の型」のように型を表現できるようにします。
要約すれば:
オーバーロードとは、同じ名前の複数の関数があり、パラメーターが異なることです。
カリー化とは、複数のパラメーターを取得し、いくつかを選択的に設定できる場所です。たとえば、変数を1つだけにすることができます。
したがって、3次元のグラフ化関数がある場合は、次のよう
justgraphit(double[] x, double[] y, double[] z)
になります。、それをグラフ化する必要があります。
カリー化することで、次のことが可能に
var fx = justgraphit(xlist)(y)(z)
なります。fxを設定して、2つの変数を設定しました。
次に、後でユーザーが別の軸(日付)を選択し、yを設定すると、次のようになります。
var fy = fx(ylist)(z)
次に、いくつかのデータをループするだけで情報をグラフ化し、唯一の変動性はz
パラメーターです。
これにより、主に設定された変数を渡し続ける必要がないため、複雑な関数が単純になり、読みやすさが向上します。