😽

Haskellのconst関数って何に使うんだろ...。

2021/04/20に公開

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

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

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

const関数とは

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

Prelude> :t const
const :: a -> b -> a

処理内容としては引数を2つ受け取り1つ目を返す処理となっています。
const関数に数値と文字列、関数を渡してみると下記のようになります。(flip関数を用いても同様のことが可能です。)

Prelude> const 1 2
1
Prelude> const "Hello" "World"
"Hello"

常に最初の値を返すのでid関数と組み合わせることで常に2つ目を返す関数も定義することが可能です。

Prelude> const id 1 2
2
Prelude> ((const id) 1) 2 --結合法則をわかりやすく記述
2

id関数のときもそうでしたが、const関数も同様に最初見たときは何のために存在する関数なのかわかりませんでした。

const関数の特徴

const関数の重要かつ、特殊なところは「必ず1つ目の引数を返すが値を得るには2つ目の引数を渡す必要がある」という性質のようです。

Prelude> foo = const 1
Prelude> :t foo
foo :: Num a => b -> a
Prelude> foo 2
1

下記でコードをもとに使い所を見ていきます。

const関数の使い所

map

定数値を返す関数を定義しておいて、どんなリストが渡されたとしても定数値に変換されたリストを生成することが可能です。

Prelude> foo = const "foo"
Prelude> map foo [1, 2, 3]
["foo","foo","foo"]

zipWith

zipWith関数と組み合わせることで2つ目のリストサイズに合わせた1つ目のリストを得ることができます。

Prelude> zipWith const [1, 2, 3] [4, 5]
[1,2]

const関数とid関数と組み合わせることで逆の1つ目のリストサイズに合わせた2つ目のリストを得ることができます。

Prelude> zipWith (const id) [1, 2] [3, 4, 5]
[3,4]

Monadの>>演算子

Monadの>>演算子は下記のようにMonad型の型制約を持っている以外はconst関数と式の型が似ています。

Prelude> :t (>>)
(>>) :: Monad m => m a -> m b -> m b

const関数を用いて下記のように定義し直すことが可能です。

Prelude> foo a b = a >>= const b
Prelude> :t foo
foo :: Monad m => m b1 -> m b2 -> m b2

つまり、>>演算子を使っている箇所で代わりにconstを用いることが可能になります。
※もちろん、素直に>>演算子を使用したほうがいいと思います。

Prelude> putStrLn "hello" >> putStrLn "world"
hello
world
Prelude> putStrLn "hello" >>= const (putStrLn "world") 
hello
world

最後に

const関数ですが基本的には必要のない値を捨てたい場合(Unit型を返す関数や上記のmapの使用例で示したような場合)に役立つということがわかりました。
その他、有識者の方でconst関数の使い所や利便性等、コメントでご教示頂ければ幸いです。

実行環境

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

参考文献

Discussion