テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

filterMの定義を見てみる

H本の中で「便利なモナディック関数特集」が組まれていて, その中にはfilterMについての説明があります. Haskellプログラミングではfilterが米であり, mapが塩とのこと. 何の比喩なのか分かりませんが, filterが大事というのは分かります. ちなみに原著では, filterがbread(block readではない. パンです)で, mapはbutterだと言っています. 訳者さんが, 日本流にアレンジしたのでしょうか?

大事ということは分かるのですが, 以下の「超かっこいい技」を披露されて, 当然だよね!と初見で思える人はたぶんあまり多くないでしょう.

*Main Control.Applicative Control.Monad> filterM (\x -> [True, False]) [1,2,3]
[[1,2,3],[1,2],[1,3],[1],[2,3],[2],[3],]

感覚的には分かります. しかし, しっくりは来ない. 一体何をしているんだろうか. そんな時は定義を見るのが良いと思います.

filterM          :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM _      =  return []
filterM p (x:xs) =  do
   flg <- p x
   ys  <- filterM p xs
   return (if flg then x:ys else ys)

定義を見ればしっくり来ます. flgは[True, False]両方の可能性をとります. そして, Trueである時はx:で前にくっつけて, Falseならくっつけません. ようするに, True, Falseの分岐を作って, 先頭にくっつけるかどうかを決めているということになります.