2009年06月21日

カリー化について考えてみる

   このエントリーをはてなブックマークに追加 Clip to Evernote
もうひとつのブログ Gushwell's F# Programming Diary に「F#: カリー化と部分適用をC#で考えてみる(1)」を掲載しましたが、F#に興味のない方は、読んでいないと思うので、こちらのブログにもアップします。

多少、文言を変えていますが、内容は同じものです。

----------

関数 f(x,y) をカリー化するとは、関数 g を

が常に成り立つ関数にすることです。

関数gの引数は、x ひとつです。xは、元の関数 f の最初の引数ですね。
関数gの戻り値は、「元の関数 f の残りの引数を取り、fと同じ型の結果を返す関数」です。つまり、戻り値は関数です。
この、カリー化の定義を、もうすこし、わかりやすいC#風のコードを使って書きなおすと、

というコードで、常に、"a == b"が表示される 関数 g を定義することが、カリー化するということになります。
----------

一応、カリー化の定義が理解できたところで、具体的な例で考えてみます。


というメソッドを例に考えると、カリー化した関数は、

となります。
いきなり、結論から入ってしまいましたが、これを噛み砕いて説明しましょう。
CurriedSum関数は、x を引数として受け取ると、

という「デリゲート (ラムダ式)」を返しています。デリゲートというのは関数のことだと思ってください。
ラムダ式がよくわからないという方は、僕のBlogのここ「ラムダ式」を読んでみてください。

この「関数」を返すというのがこのCurriedSum関数の肝です。 なので、CurriedSum(10) と呼び出すと、

というデリゲート(int y を受け取り、10+y の結果を返す関数)が返ってきます。
なので、このカリー化した関数の使い方は


となります。引数が2つあったのが、一つずつ与える形に変更されたのがわかると思います。
つまり、

が成立したということです。
カリー化した関数は、こんな書き方もできます。

これで面白いのは、

などと書けることです。最初の 10 という引数をずーっと保持し続けることができます。
ということは、

のように、インクリメントする関数を定義することができます。
このように、カリー化した関数を呼び出し、あらたな関数を得ることを部分適用といいます。

関数型言語ではよく使われるみたいですが、普通のC#プログラマーは、こういったコードはまず書かないと思います。
なので、僕も、どう便利なのかがいまいち実感がありません。


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/51843020