The Haskell 98 Report
top | back | next | contents | function index
module Monad ( MonadPlus(mzero, mplus), join, guard, when, unless, ap, msum, filterM, mapAndUnzipM, zipWithM, zipWithM_, foldM, liftM, liftM2, liftM3, liftM4, liftM5, -- ...and what the Prelude exports Monad((>>=), (>>), return, fail), Functor(fmap), mapM, mapM_, sequence, sequence_, (=<<), ) where class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a join :: Monad m => m (m a) -> m a guard :: MonadPlus m => Bool -> m () when :: Monad m => Bool -> m () -> m () unless :: Monad m => Bool -> m () -> m () ap :: Monad m => m (a -> b) -> m a -> m b mapAndUnzipM :: Monad m => (a -> m (b,c)) -> [a] -> m ([b], [c]) zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c] zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m () foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] msum :: MonadPlus m => [m a] -> m a liftM :: Monad m => (a -> b) -> (m a -> m b) liftM2 :: Monad m => (a -> b -> c) -> (m a -> m b -> m c) liftM3 :: Monad m => (a -> b -> c -> d) -> (m a -> m b -> m c -> m d) liftM4 :: Monad m => (a -> b -> c -> d -> e) -> (m a -> m b -> m c -> m d -> m e) liftM5 :: Monad m => (a -> b -> c -> d -> e -> f) -> (m a -> m b -> m c -> m d -> m e -> m f) |
Monad ライブラリは MonadPlus クラスを定義し、 モナド上のいくつかの有用な演算を定義している。
このライブラリ内の関数の名前は以下の慣習に従う。
接尾辞 "M" は常にその関数が Kleisli カテゴリーの関数である
ことを示している。m が関数の結果に付与される(modulo currying).
これは他では現れない。例としては、
filter :: (a -> Bool) -> [a] -> [a]
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
接尾辞 "_" は結果の型を (m a) から
(m ()) へ変更する.たとえば(Preludeでは):
sequence :: Monad m => [m a] -> m [a]
sequence_ :: Monad m => [m a] -> m ()
接頭辞 "m" は既存の関数をモナド形式に一般化するものである。
たとえば、(Preludeでは),
sum :: Num a => [a] -> a
msum :: MonadPlus m => [m a] -> m a
MonadPlus クラスは以下のように定義されている。
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
クラスメソッド mzero および mplus はモナドにおけるゼロ
および加法である。
リスト型および Maybe 型は MonadPlus
のインスタンスである。すなわち、
instance MonadPlus Maybe where
mzero = Nothing
Nothing `mplus` ys = ys
xs `mplus` ys = xs
instance MonadPlus [] where
mzero = []
mplus = (++)
join 関数は旧来のモナドの join 演算子である。この演算子は モナド構造の一つのレベルを除去し、その束縛引数を外側のレベルに 投射するものである。
mapAndUnzipM 関数は第一引数をリスト上でマップしてリストの 組を返す。この関数は主に、複雑なデータ構造あるいは状態変換モナドと ともに使用される。
zipWithM 関数は zipWith を任意のモナドへ一般化した
ものである。例えば、以下の関数はファイルを表示し、その行の先頭に
行番号を付けるものである。
listFile :: String -> IO ()
listFile nm =
do cts <- readFile nm
zipWithM_ (\i line -> do putStr (show i); putStr ": "; putStrLn line)
[1..]
(lines cts)
foldM 関数は foldl のアナロジーである。結果が
モナドに包まれていることは除いて。foldM はリスト引数の
左から右へ作用していくことに注意すること。このことは、
(>>) および "畳み込み関数"が可換ではないところで問題と
なりうる。
foldM f a1 [x1, x2, ..., xm ]
==
do
a2 <- f a1 x1
a3 <- f a2 x2
...
f am xm
もし、右から左へ評価する必要があるなら、入力のリストを逆順に
しなければならない。
when および unless 関数はモナド式の条件実行を
おこなう。たとえば、
when debug (putStr "Debugging\n")
は、もしブール値 debug が True なら、文字列
"Debugging\n" を出力し、そうでなければ、なにもしない。
モナド持ち上げ演算は関数をモナドへプロモートする。関数引数は左から
右へ走査される。たとえば、
liftM2 (+) [0,1] [0,2] = [0,2,1,3]
liftM2 (+) (Just 1) Nothing = Nothing
多くの状況で、liftM 演算は 関数適用をプロモートする ap
を使うことで置き換え可能である。
return f `ap` x1 `ap` ... `ap` xn
は、
liftMn f x1 x2 ... xn
と同等である。
module Monad (
MonadPlus(mzero, mplus),
join, guard, when, unless, ap,
msum,
filterM, mapAndUnzipM, zipWithM, zipWithM_, foldM,
liftM, liftM2, liftM3, liftM4, liftM5,
-- ...and what the Prelude exports
Monad((>>=), (>>), return, fail),
Functor(fmap),
mapM, mapM_, sequence, sequence_, (=<<),
) where
-- The MonadPlus class definition
class (Monad m) => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
-- Instances of MonadPlus
instance MonadPlus Maybe where
mzero = Nothing
Nothing `mplus` ys = ys
xs `mplus` ys = xs
instance MonadPlus [] where
mzero = []
mplus = (++)
-- Functions
msum
:: MonadPlus m => [m a] -> m a
msum xs
= foldr mplus mzero xs
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
when :: (Monad m) => Bool -> m () -> m ()
when p s = if p then s else return ()
unless :: (Monad m) => Bool -> m () -> m ()
unless p s = when (not p) s
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap = liftM2 ($)
guard :: MonadPlus m => Bool -> m ()
guard p = if p then return () else mzero
mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip
zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM f xs ys = sequence (zipWith f xs ys)
zipWithM_ :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ f xs ys = sequence_ (zipWith f xs ys)
foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM f a [] = return a
foldM f a (x:xs) = f a x >>= \ y -> foldM f y xs
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM p [] = return []
filterM p (x:xs) = do { b <- p x;
ys <- filterM p xs;
return (if b then (x:ys) else ys)
}
liftM :: (Monad m) => (a -> b) -> (m a -> m b)
liftM f = \a -> do { a' <- a; return (f a') }
liftM2 :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c)
liftM2 f = \a b -> do { a' <- a; b' <- b; return (f a' b') }
liftM3 :: (Monad m) => (a -> b -> c -> d) ->
(m a -> m b -> m c -> m d)
liftM3 f = \a b c -> do { a' <- a; b' <- b; c' <- c;
return (f a' b' c') }
liftM4 :: (Monad m) => (a -> b -> c -> d -> e) ->
(m a -> m b -> m c -> m d -> m e)
liftM4 f = \a b c d -> do { a' <- a; b' <- b; c' <- c; d' <- d;
return (f a' b' c' d') }
liftM5 :: (Monad m) => (a -> b -> c -> d -> e -> f) ->
(m a -> m b -> m c -> m d -> m e -> m f)
liftM5 f = \a b c d e -> do { a' <- a; b' <- b; c' <- c; d' <- d;
e' <- e; return (f a' b' c' d' e') }
The Haskell 98 Report
top | back | next | contents | function index
December 2002