関数

【Haskell】高階関数の基本

【Haskell】高階関数の基本

関数型プログラミング言語における中心的な概念である高階関数の基本について解説します。

高階関数の基本概念

高階関数(Higher-order functions)は、関数型プログラミング言語における中心的な概念で、プログラミングにおける表現力を大きく高めることができます。

高階関数は、他の関数を引数として受け取るか、または結果として関数を返すことができます。この特徴により、コードの再利用性が向上し、より柔軟なプログラミングが可能になります。

本記事では、高階関数の特徴やHaskellにおける実装例を紹介します。

高階関数の特徴

高階関数は、以下のような特徴を持つ関数です。

特徴説明
第1級オブジェクトとしての関数Haskellを含む多くの関数型プログラミング言語では、関数を第1級オブジェクトとして扱います。
第1級オブジェクトは、変数に割り当てたり、データ構造に格納したり、他の関数に引数として渡したり、関数からの戻り値として返すことが可能です。
抽象化と再利用性の向上高階関数を使用すると、特定の操作を抽象化し、異なる文脈(コンテキスト)での再利用性が高まります。
コードの簡潔化高階関数を使用により、コードをより簡潔にし、意図を明確にすることができます。複雑なループや条件分岐を抽象化して、コードの読みやすさと保守性を向上できます。

高階関数は、上記のような非常に有用な特性を持っているため、Haskellのような関数型プログラミング言語に限らず様々な言語でも取り込まれていっています。例えば、Pythonはマルチパラダイム言語であり、高階関数を使用することが可能です。Pythonのデコレータは、高階関数を用いた仕組みを簡単に利用できるようにする仕組みとして機能しています。

ただし、高階関数は良い側面ばかりとも言えません。高階関数を過度に使用することでコードの読みにくさを引き起こす可能性があったり、デバッグがしにくくなる可能性もある点は理解しておいてください。

高階関数のHaskell実装例

ここでは、Haskellでの実装例を使って高階関数のイメージをつかんでもらおうかと思います。高階関数を実装する際には、関数を受け取るか、または関数を返すようにします。例として、二つの関数を合成する高階関数composeをHaskellで実装してみます。

-- 2つの関数を合成する関数
compose :: (b -> c) -> (a -> b) -> a -> c
compose f g x = f (g x)

上記関数は、関数f、関数gと入力xを受け取って、xgを適用し、その結果にfを適用するという関数になっています。つまり、数学的に書いてみるとf(g(x))を返す関数です。

では、この関数をうまく使って、5を加算する関数(add5)と2を乗算をする関数(multiply2)を順番に適用するような関数を作ることを考えてみましょう。

-- 5を加算する関数
add5 :: Int -> Int
add5 x = x + 5

-- 2を乗算する関数
multiply2 :: Int -> Int
multiply2 x = x * 2

上記の二つの関数を順番に適用する関数は、composeを使って以下のように定義できます。

-- add5を適用してから、multiply2を適用する関数
add5AndMultiply2 :: Int -> Int
add5AndMultiply2 = compose multiply2 add5

ここで、compose関数は、関数自体を引数に渡すことができるため、引数の部分に「add5」や「multiply2」といった関数を指定することができます。この式は「add5AndMultiply2 x = compose multiply2 add5 x」とも書けますが、Haskellでは、η簡約(eta reduction)でxを省略することができます。

上記の定義は、compose関数が「Int型のxを受け取ってIntの結果を返却するような関数」を返却し、その関数がadd5AndMultiply2に割り当てられていることを意味します。

具体的に使用例を見てもらえるとイメージがつかみやすいかもしれません。ghciというHaskellのインタプリタを使ってadd5AndMultiply2実行した結果は以下の通りです。

ghci> add5AndMultiply2 5
20
ghci> add5AndMultiply2 10
30

上記の結果から、add5AndMultiply2が、5を加算する関数(add5)と2を乗算をする関数(multiply2)を順番に適用するような関数となっていることが分かるかと思います。

このように関数の組み合わせが簡単に実現できてしまいました。これは、関数を引数に取ったり、関数を返却したりできる高階関数のおかげです。

Note

【η簡約(eta reduction)とは】

η簡約(エータ簡約)は、関数型プログラミングにおける概念の一つで、関数の定義をより簡潔にするための方法です。具体的には、「関数がただ別の関数に引数を渡すだけの場合、その引数を省略して書くことができる」というルールに基づきます。これにより、コードがシンプルになり、読みやすくなります。

例えば、Haskellでの関数定義を考えた際に、もし関数fが引数xを受け取って、そのまま別の関数gxを渡すだけの場合、つまりf x = g xという形であれば、ff = gと書き換えることができます。この時、引数xが省略され、より簡潔な形で関数を表現できます。

このように、η簡約は「関数が引数を介してただ他の関数を呼び出すだけの場合、その引数を省略しても同じ意味を持つように書ける」という考え方です。これはコードをシンプルに保ち、冗長性を減らすのに役立ちます。

まとめ

関数型プログラミング言語における中心的な概念である高階関数の基本について解説しました。

高階関数は、他の関数を引数として受け取るか、または結果として関数を返すことができ、コードの再利用性や柔軟性を向上させます。今回は、Haskellの簡単な高階関数の実装を通して、高階関数のイメージをつかんでもらいました。

高階関数は、関数型プログラミング言語における中心的な概念で、プログラミングにおける表現力を大きく高めるものです。是非考え方をしっかり理解して使いこなしてもらいたいと思います。