カリー化と部分適用
部分適用は、カリー化によって可能となる。
では、カリー化とは。
すべての関数は一引数の関数として扱うこと。
f :: Num a => a -> a -> a
と定義された関数があるとき、fは2引数の関数である。
これに、例えば Numクラスに属する型の値 x を適用すると、(これが部分適用)
値を適用された関数は、fとは異なる関数として表現できる。
f x :: Num a => a -> a
となる。
実際にGHCiで実験してみる。
まず、関数 f を、以下のように定義
f :: Num a => a -> a -> a f x y = x + y
Prelude> :t f f :: Num a => a -> a -> a Prelude> let x = 2 Prelude> :t f x f x :: Integer -> Integer
このようになります。
もしここで
f 123 456
のようにすると、これは、
まず f に123を適用。
→f y = 123 + y のように、一つの引数を適用し、関数を生成。
→ 456 を適用。
のような流れを追う。
Haskellでは、多分すべての関数はカリー化が可能。(どうなんだろ)
そして部分適用によって得られるのは値。
なので、以下のようなことも可能
まずはソースコード
module CurryTest where myany :: Char -> String -> Bool myany _ [] = False myany c (s:str) = if c == s then True else myany c str myany' :: Char -> (String -> Bool) myany' c = myany c
そしてGHCiで実行。
*CurryTest> myany 's' "Haskell" True *CurryTest> :t myany' 's' myany' 's' :: String -> Bool *CurryTest> myany' 's' "Haskell" True
Haskell使う過程で、誰もが一度は見たことがあると思われる
map (+2) numberlist
も、部分適用によってカリー化された関数をリストの各要素に適用しているのと同じ。
また、コメントをもらいましたが、
タプルを引数に取る関数
g :: (a,b) -> b -> a
のような関数があったときに、
g' :: a -> b -> b -> a
のように変換することも、これは、複数のデータを展開し、上で扱ってきたような関数と同等にすることでカリー化していることになるようです。