あどけない話

インターネットに関する技術的な話など

関数合成の妙技

Haskell 初心者は括弧ばかりの Lisp のようなコードを書く。中級者になると、($) が多くなる。上級者(言い過ぎか?)になると、($) が消えて、(.) が多くなる。この記事では、上級者になるコツをちょっと教えちゃおう。

括弧だらけのコード

では、以下の例について考えよう。

foo p xs = sum (filter p (map (+1) xs))

括弧が多くて、いかにも初心者が書いたコードだ。foo は、以下のように動く。

foo even [1..6]
→ 12

($) を使う

では、括弧を ($) に置き換えてみよう。そうするには、一番右側にある閉じ括弧を消して、対応する開き括弧を ($) に置き換えればよい。だからこうなる。

foo p xs = sum $ filter p $ map (+1) xs

だいぶ見やすくなった。

(.) を使う

map (+1) xs は、(map (+1)) xs という意味で、map (+1) (xs) とも解釈できるから、括弧を($)に置き換える手法を適用して、以下のように変形できる。

foo p xs = sum $ filter p $ map (+1) $ xs

こうなると、右辺の最後の変数以外は、一引数の関数の連なりになるから、($) を (.) で置き換えられる。

foo p xs = sum . filter p . map (+1) $ xs

そして、右辺と左辺の最も右側に xs があるので、これを削ることができて、最終的にはこうなる。

foo p = sum . filter p . map (+1)

これで、Haskell らしいコードのできあがり。