『入門Haskell』練習問題例解(14)
p.128。モナド関連の関数です。
1. sequence_ を foldr を使って定義しなさい。
2. mapM と mapM_ を定義しなさい(sequenceなどを使ってもよい)。
3. foldM と foldM_ を定義しなさい。
sequence_
mySequence_ :: Monad m => [m a] -> m () mySequence_ = foldr (>>) (return ())
こうなります。ちなみに、sequence を foldr を使って定義すると
mySequence :: (Monad m) => [m a] -> m [a] mySequence = foldr ((flip (.) (((flip (.) ((return .) . (:))) . (>>=)))) . (>>=)) (return [])
となります。もはや何がなんだか…
mapM, mapM_
mapM f = (\x -> sequence (map f x)) => (\x -> sequence ((map f) x)) => (sequence . (map f)) => (\x -> sequence . (map x)) f => ((sequence .) . map) f
なので、最終的には
myMapM :: Monad m => (a -> m b) -> [a] -> m [b] myMapM = (sequence .) . map myMapM_ :: Monad m => (a -> m b) -> [a] -> m () myMapM_ = (sequence_ .) . map
となります。
foldM, foldM_
foldM f a [x1, x2, ... ,xn] は
f a x1 >>= (\y -> f y x2) >>= ... >>= (\y -> f y xn) >>= (\y -> f y [])
と同じことです。flip関数を使ってyが消去できるので、答えは
myFoldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a myFoldM f a [] = return a myFoldM f a (x:xs) = (f a x) >>= (flip (myFoldM f) xs) myFoldM_ :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m () myFoldM_ f a [] = return () myFoldM_ f a (x:xs) = (f a x) >>= (flip (myFoldM_ f) xs)
となります。
次回、最終回!