Haskell で for 文


Haskell で無理矢理 for 文を書こうとしたらどうなるかなと思って書いてみました。

for init cond next action
   | cond init = action init : for (next init) cond next action
   | otherwise = []
forM init cond next action = sequence (for init cond next action)
forM_ init cond next action = sequence_ (for init cond next action)

それぞれの型は以下の通りです。

for :: t -> (t -> Bool) -> (t -> t) -> (t -> a) -> [a]
forM :: Monad m => t -> (t -> Bool) -> (t -> t) -> (t -> m a) -> m [a]
forM_ :: Monad m => t -> (t -> Bool) -> (t -> t) -> (t -> m a) -> m ()

どう見ても mapmapMmapM_ です。本当にありがとうございました[A]。ちなみに本物の map 系の型は以下の通り。

map :: (a -> b) -> [a] -> [b]
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()

せっかくなので使ってみましょう。

*Main> for 0 (<10) succ id
[0,1,2,3,4,5,6,7,8,9]
*Main> forM 5 (>0) pred Just
Just [5,4,3,2,1]
*Main> forM_ 1 (<1000) (*3) print
1
3
9
27
81
243
729

init cond next はタプルにした方が for 文っぽい感じが出るかもしれませんね。

脚注

  1. [2011-10-31 09:00 追記] 上記の formap で書き直せば map action $ takeWhile cond (iterate next init) になるので当たり前ですね []