10周年のSPコンテンツ!

Haskellのカリー化の話。

Haskellのcurry関数とカリー化と部分適用についてまとめ。 ・Haskellのcurry関数は、タプルを取る関数を高階関数化しているので、タプルを取る関数を多変数関数、とみなせばcurry化というのは妥当ということ。 ・カリー化している関数に部分適用すること自体はできないということ 続きを読む
プログラミング
4

・curry :: ((a, b) -> c) -> a -> b -> c
という関数について、
((a, b) -> c)をa -> b -> cとするのはカリー化といえるか?
ということの考察。

Haskellで言うカリー化と言われているのは、
(\x y = x + y) => (\x -> (\y -> x + y))
という変換であり、
Haskellのcurry関数は、
(\(x,y) -> x + y) => (\x -> (\y -> x + y))
という変換をしているのであり、curry関数は「Haskellのカリー化」と言えない。

しかし、直積の集合を取る関数 f:(A x B)->Cを、g:A->(B->C)と捉えるならば、タプルを取る関数は直積集合を取る関数と捉えられ、先のcurry関数の変換ほうがむしろカリー化として妥当じゃないではないか?ということ。

はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
Haskellのcurryとuncurry関数をcurryなのか?というとすごい微妙だと思う。A x B -> Cという関数A -> B -> Cとするのがカリー化だと思うが、A x Bという直積をタプルと捉えようと思えば思えるけど、タプルを取る1引数関数を変換しただけともとれる
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
Haskellは多変数関数を、複数の変数を内包したタプルを取る関数と捉えるならば、curry関数はcurryと言える。
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
多変数関数のことを、組の関数と取れば、タプルとる1引数関数が多変数関数だな。
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
Haskellのタプルを取る関数を多変数関数とすれば、たとえば、(\x y -> x + y)というのは多変数関数ではないよね。引数がタプルじゃないもん。ただの(\x -> (\y -> x + y))のシンタックスシュガーとも言えるんじゃないか?

もしHaskellのcurry関数の変換の方をカリー化と捉えるならば、
(\x y -> x + y) => (\x -> (\y -> x + y))
というのは、いったい何者なのか?

(\x y -> x + y)
というのは、実は2引数関数ではなくて、
ただの
(\x -> (\y -> x + y))
へのシンタックスシュガーではないかということ。

つまりHaskellの関数ははそもそもカリー化されているのではなく、多引数関数を作ることが出来ないようになっているということ。

はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
だからHaskellは、むしろタプル無しで複数の引数を持つ関数は作ることが出来ないといことか。カリー化しちゃうからねー。
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
カリー化されてない関数が部分適用できるのであって、カリー化されていると部分適用はできないよな。1引数関数だから部分なんて無い。
ちゅーん @its_out_of_tune
基本的には const x = \y -> x も const x y = x も記法の違いと考えてる。実装は不知火。
ちゅーん @its_out_of_tune
Haskellはそもそも多引数を取る関数が無いので、すべての関数がカリー化されてるという表現は厳密には正しくないと思ってる。
ちゅーん @its_out_of_tune
もともとカリー化もクソもないので、部分適用と言う語も適切ではないという事になっちゃうんだけど、必要であれば便宜的に使うかなぁ。
ちゅーん @its_out_of_tune
部分適用の過程にカリー化あると考えるのが一番しっくり来るな。
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
@its_out_of_tune 僕もある程度そう思うんだけど、部分適用は、たとえば、f(x,y,z)があったとすると、変数の一部を束縛した関数、f'(y) = f(x =Y, y, z=Z)と返す訳で、その過程で必ずしもカリー化されているか?といえそうでは無い気がする。
ちゅーん @its_out_of_tune
@nobkz 難しいな…f'(y)=f(x=X, y)と、curry(f)(X) は外延的に等価なだけであって、部分適用とカリー化に直接的な関係は無いだけとゆー事かしら…
はなだ☆のぶかず@lisp &ボドゲ勢ボドゲプレイヤー) @nobkz
@its_out_of_tune 多分そう言うことだと思う。こう考えると意外と部分適用とカリー化がややこしいことになってると思う。けれども、実際にはある程度混同してもそうそう困ること無いんじゃない?
ちゅーん @its_out_of_tune
@nobkz ですねー。大体Haskellで「カリー化されてる」と言えば高階になってるという意味合いですし、部分適用といえば高階関数に引数を与える事なので、よくある「部分適用の事をカリー化と呼ぶ」レベルの間違いでなければさしたる問題は無いと思いまふー。

コメント

XENO @xenophobia__ 2013年8月22日
Wikipediaの"partial application"の頁には部分適用=「引数をいくつか固定し、よりarityの少ない関数を生成する手続き」とあって、一方で"arity"の頁には「(数学的な意味では)arity nとは定義域がn個の直積であることである」ってあるから、そう考えるとHaskellで言う「部分適用」が本当に厳密に部分適用なのかはあやしいかもしれない。
XENO @xenophobia__ 2013年8月22日
でも普通"f n m = n + m"とか書いてあったらarity=2って考えちゃうし、計算機科学にはそう見做してる論文もあるから、「数学的に厳密か」の議論に拘るのもよくないかもしれないですね。
桜浴衣王さん✬ @Dr_sakura 2013年8月22日
いい匂いのしてくる話かと思ったら違ったので、帰ります。
ログインして広告を非表示にする
ログインして広告を非表示にする