Haskellerへの道 #5 - カリー化

Last Edited: 6/17/2024

このブログ記事では、関数型プログラミング(Haskellを含む)において重要な概念であるカリー化の概念を紹介しています。

Haskell & Curry

カリー化

カリー化は、関数型プログラミングの概念の一つで、多くの初心者が混乱しやすい概念です。カリー化は 関数をカレー味にすることではなく、複数の引数を持つ関数が、それぞれ1つの入力を持つ内包された関数として解釈されることを指します。

func:: a -> b -> c -> d
func:: a -> (b -> (c -> d))

この概念により、Haskellは一部のプログラマーには予想外の動作をすることがあります。簡単な例を見てみましょう。

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

上記の関数addは、xyを入力として受け取ります。しかし、次のように関数をリファクタリングすることができます。

add :: Int -> Int -> Int
add x = (\y -> x + y)

ここでは、関数はxだけを入力として受け取りますが、yは関数内に存在します。命令型プログラミング言語では、 これは受け入れがたいはずですが、Haskellでは関数が値として扱われるため、これは合法です。関数が関数を返すことは完全に許容されます。 add関数の場合、上記の例は次に提供されるyに対してxを加える別の関数を返します。

add 1 --- Output: (\y -> 1 + y)
add 1 2 --- Output: 3

関数を少ない引数の関数に変換することを部分関数適用と呼び、関数型プログラミングでは広く利用されています。

実例

部分関数適用が実際にどのように使用されるかを見てみましょう。前の記事で取り上げたmap関数が良い例です。正しく覚えていれば、map関数は次のように適用できることがわかります。

map (\x -> x + 2) [1,2,3,4,5] --- Output: [3,4,5,6,7]

しかし、同じ匿名関数を複数回使用したい場合はどうでしょうか?(\x -> x + 2)を何度も入力する必要があるのでしょうか?幸いなことに、ここで部分関数適用を利用できます。

add2ToList = map (\x -> x + 2)

リストの要素に2を加える新しい関数が作成されました。この関数は何度でも再利用可能です。

クイズ

この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。

リソース