top page > computer > haskell > web_lecture > for_programmer > curry.html
更新日:
文責: 重城良国

カリー化

自己紹介

名前と年齢をまとめたタプルを引数にして自己紹介の文字列を返す関数を考える。

introduction.hs

introduction :: (String, Integer) -> String
introduction (n, a) =
"My name is " ++ n ++
". I'm " ++ show a ++ " years old."

関数showは値を表示用の文字列に変換する。

% ghci introduction.hs
*Main> introduction ("Yoshikuni Jujo", 35)
"My name is Yoshikuni Jujo. I'm 35 years old."

年齢は変わる

名前は変わらないが年齢は変わる。サバを読むこともある。

*Main> introduction ("Yoshikuni Jujo", 10)
"My name is Yoshikuni Jujo. I'm 10 years old."

「僕はまだ小4だよ」。バレたら本当のことを言おう。

*Main> introduction ("Yoshikuni Jujo", 35)
"My name is Yoshikuni Jujo. I'm 35 years old."

サバ読むときやバレたときのことを考えて"Yoshikuni Jujo"専用の自己紹介関数を作る。名前だけに部分適用したいが名前と年齢はタプルにまとまっていて部分適用できない。

そこでカリー化ですよ

Haskellにおけるカリー化とは

カリー化で複数の引数をとる関数は関数を返す関数になる。これで部分適用が可能になる。Haskellでは複数の引数を取る関数(のようなもの)ははじめから関数を返す関数だ。他の言語での「複数の引数をとる関数」は「タプルを引数にとる関数」に相当する。よって、Haskellでのカリー化を「タプルを引数に取る関数を複数の引数を取る関数(のようなもの)に変換すること」と定義する。

試してみる

*Main> :t introduction
(String, Integer) -> String
*Main> :t curry introduction
String -> Integer -> String
*Main> curry introduction "Yoshikuni Jujo" 35
"My name is Yoshikuni Jujo. I'm 35 years old."

タプルとして与えるべき引数をばらばらに与えられる。これを使ってYoshikuni Jujo専用の自己紹介関数を作成する。

introductionYj :: Integer -> String
introductionYj = curry introduction "Yoshikuni Jujo"

*Main> :reload
*Main> introductionYj 35
"My name is Yoshikuni Jujo. I'm 35 yeras old."
*Main> introductionYj 10
"My name is Yoshikuni Jujo. I'm 10 years old."

関数curryの型と定義

関数curryは「引数としてタプルを期待する関数」の引数をばらばらにする。

上の例は(String, Integer) -> StringString -> Intege -> Stringに変換している。

((String, Integer) -> String) -> (String -> Integer -> String)

一般化する。

((a, b) -> c) -> (a -> b -> c)

「(a, b)型のタプルをとってc型の値を返す関数」を「a型の値とb型の値をとってc型の値を返す関数」に変換する。'->'は右結合なので右側の丸括弧は省略できる。

((a, b) -> c) -> a -> b -> c

右側の丸括弧を省略することで以下のように読める。「タプルを取る関数」とそのタプルの第1要素と第2要素を引数としてとり「第1引数の関数の返り値の型」の値を返す。

定義

curry :: ((a, b) -> c) -> a -> b -> c
curry f x y = f (x, y)

[関数curryの図]

関数curryの第2引数xと第3引数yというばらばらの引数をタプルにまとめて関数fに与える。

課題

  1. 年齢と公開可能かどうかのブール値のタプルをとり適切に文字列化する関数を作成せよ
  2. 上記関数を年齢(例えば39)だけに部分適用せよ
  3. 3整数タプルの要素が三角形の3辺になることを確認する関数triangleを作成せよ
  4. 3要素タプルを引数としてとる関数を3引数関数に変換するcurry3を定義せよ

「タプル: 原点からの距離」へもどる 「非カリー化」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics