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
inc
は add 1
の返り値、つまり 「1 を加える関数」として定義されている。
とりあえず、まとめ
- 関数適用は左結合
- 型の
->
は右結合 - 関数の部分適用ができる