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 ()
どう見ても map
, mapM
, mapM_
です。本当にありがとうございました[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
文っぽい感じが出るかもしれませんね。
脚注
- [2011-10-31 09:00 追記] 上記の
for
をmap
で書き直せばmap action $ takeWhile cond (iterate next init)
になるので当たり前ですね [↩]