Haskell 始めてみる(08)

3関数より。

add                     :: Integer -> Integer -> Integer
add x y                 =  x + y

これは、カリー化(curry)された関数の一例です。アンカリー化(uncurry)された関数をえるには、タプルを使います。

add (x,y)               = x + y

カリー化された関数、アンカリー化された関数という表現をするのか。でもアンカリー化した関数なんてあまりありがたくない気がする。
カリー化の意味は、以下から推測。

関数 add の適用は add e1 e2 という形式になります。これは、 (add e1) e2 と同等の式です。なぜかというと関数適用は左結合性をもつからです。いいかえれば、関数 add を最初の引数に適用すると、新しい関数ができて、これをふたつめの引数に適用するということです。このことは、関数 add の型 Integer->Integer->Integer とも整合がとれています。この型は、Integer->(Integer->Integer) と同等のものです。ここで、 -> は右結合性をもっています。

確認。

add                     :: Integer -> Integer -> Integer
add x y                 =  x + y

型を見てみる。

 *Main> :t add
 add :: Integer -> Integer -> Integer
 *Main> :t add 1
 add 1 :: Integer -> Integer
 *Main> :t add 1 2
 add 1 2 :: Integer

add の型は Integer -> Integer -> Integer で、これは整数 2 個を引数に取って、整数を返す関数型と読めばよい。-> でつながった型のうち、最後の型が返り値で、それ以外が引数の型。
関数適用が左結合というのが面白い。普通っちゃ普通だけど。右結合は考えにくいし。
で、関数の型の -> が右結合ということとうまくかみ合ってとてもよい感じ。
型が右結合という事は、括弧を補って

Integer -> (Integer -> Integer)

としても同値。この表現をそのまま読むと、整数 1 個を引数に取って、「整数 1 個を引数に取って整数を返す関数」を返す関数となる。上の例だと、add に引数 1 を渡したものの型が

 *Main> :t add 1
 add 1 :: Integer -> Integer

となって、ちゃんとつじつまが合っている。素晴らしい。
ややこしいけどもう一度整理すると、

add は、

  • 整数 2 個を引数にとって、整数を返す関数

であり、

  • 整数 1 個を引数に取って、「整数 1 個を引数に取って整数を返す関数」を返す関数

でもある。
ということ。

こういうのを関数の部分適用というらしい。
カリー化された関数の定義は書いてないけど、部分適用が可能な関数と思っていいんじゃないかと。ということは、ほとんどの普通に書かれた関数は既にカリー化されてるなぁ。

部分適用と、関数が第一級の対象ということを示すのが次。

inc                    = add 1

incadd 1 の返り値、つまり 「1 を加える関数」として定義されている。

とりあえず、まとめ

  • 関数適用は左結合
  • 型の -> は右結合
  • 関数の部分適用ができる