💨

Haskellのid関数って何に使うんだろ…。

2 min read

Haskellの学習を進めて中でid関数が出てきた際の疑問

「Haskellのid関数って何に使うんだろ...。」

を解消すべく調査しました。

id関数とは

ひとまずid関数の式の型を見てると下記となります。

Prelude> :t id
id :: a -> a

型変数aが使用されているため多相型で、idは多相関数であることがわります。
しかし、処理内容は引数を一つ受け取り、そのまま引数を返す処理になってます。
id関数に数値と文字列を渡してみると下記のようになります。

Prelude> id 1
1
Prelude> id "Hello World"
"Hello World"

最初見たときは何のために存在する関数なのかわかりませんでした。

id関数の存在意義

id関数に関して参照先のstackoverflowに下記の説明がありました。

It's useful as an argument to higher order functions (functions which take functions as arguments), where you want some particular value left unchanged.

訳すと「これは、高階の関数(関数を引数にとる関数)の引数として、ある特定の値を変更せずに残したい場合に便利です。」という意味になります。
つまり、高階関数に変更を加えずに関数を渡したい場合に使用できるという意味でしょうか。
この説明もわかりにくいかもしれませんが...。
下記でコードをもとに使い所を見ていきます。

id関数の使い所

zipWith

zipWith関数を使用する際にid関数を用いてみます。
1つ目の配列[a]が引数を1つ受け取る関数の配列だった場合にid関数が使用できます。

Prelude> zipWith id [(+2), succ, id] [3, 2, 1]
[5,3,1]

foldr

foldr関数を使用する際にid関数を用いてみます。
1つ目の引数に.関数(関数合成を行う関数)を渡し、id関数と引数を1つ受け取る関数のリストを渡すことで部分適応された関数を作成できます。
部分適応されているので必要な最後の引数(ここでは7を渡している)を渡すことで演算結果が表示されます。

Prelude> :t foldr (.) id [(+2), (*2)]
foldr (.) id [(+2), (*2)] :: Num b => b -> b
Prelude> foldr (.) id [(+2), (*2)] 7
16

Monoid

関数のモノイドのインスタンス宣言を行う際のmempty(単位元)として使用することができます。
memptyはx <> id =x(及びid <> x = x)であることを意味します。
なので整数の乗算では1、整数の加算では0になります。

instance Monoid (a -> a) where
        mempty        = id
        f `mappend` g = (f . g)

最後に

そもそもid関数は恒等関数(Identity function)の略で数学から持ち込まれている概念です。
そのためもっと深くid関数の有用性を理解するには数学での恒等関数の様々な用途を学んでいけばいいような気がしました。

実行環境

OS:Debian GNU/Linux 10 (buster)
GHC:The Glorious Glasgow Haskell Compilation System, version 8.4.4

参考