Control.Monad
module Control.Monad (
Functor(fmap), Monad((>>=), (>>), return, fail), MonadPlus(mzero, mplus),
mapM, mapM_, forM, forM_, sequence, sequence_, (=<<), (>=>), (<=<),
forever, void, join, msum, filterM, mapAndUnzipM, zipWithM,
zipWithM_, foldM, foldM_, replicateM, replicateM_, guard, when,
unless, liftM, liftM2, liftM3, liftM4, liftM5, ap
) where
Control.Monad
モジュールはFunctor
, Monad
, MonadPlus
クラスと、いくつかのモナド上の便利な演算子を提供する。
(訳注: 以下の説明は現状のGHCの提供するものとは異なっています。)
FunctorとMonadクラス
型クラス
class Functor f where
Functor
クラスはそれ上にマップできるような型に使われる。Functor
インスタンスは次の法則を満たすべきである:
fmap id == id
fmap (f . g) == fmap f . fmap g
リスト、Data.Maybe.Maybe
、System.IO.IO
に対するFunctor
のインスタンスはこの法則を満たす。
メソッド
fmap :: (a -> b) -> f a -> f b
インスタンス
instance Functor []
instance Functor IO
instance Functor Maybe
instance Ix i => Functor (Array i)
型クラス
class Monad f where
Monad
クラスはモナド上の基本的な演算子を定義する。モナドは圏論と呼ばれる数学の一分野から来た概念である。しかしながら、Haskellプログラマの観点からはモナドはアクションの抽象データ型のことであると思うのが最適である。Haskellのdo
式はモナディックな式を書くための便利な構文を提供している。
最小完全定義: >>=
とreturn
Monad
のインスタンスは次の法則をみたすべきである:
return a >>= k == k a
m >>= return == m
m >>= (\x -> k x >>= h) == (m >>= k) >>= h
Monad
とFunctor
のインスタンスは追加で次の法則も満たすべきである。
fmap f xs == xs >>= return . f
Preludeで定義されているリスト、Data.Maybe.Maybe
、System.IO.IO
に対するMonad
のインスタンスはこの法則を満たす。
メソッド
(>>=) :: m a -> (a -> m b) -> m b
最初のアクションによって生成された値を2つ目のアクションの引数として渡すことで連続して2つのアクションを合成する。
(>>) :: m a -> m b -> m b
最初のアクションによって生成された値を捨てることで連続して2つのアクションを合成する。これは手続き型言語での順列を表す演算子(例えばセミコロン)のようなものである。
return :: a -> m a
値をモナディックな型に注入する。
fail :: String -> m a
メッセージとともに失敗する。この演算子はモナドの数学的な定義の一部ではないが、do
式の中でパターンマッチに失敗した際に呼ばれる。
インスタンス
instance Monad []
instance Monad IO
instance Monad Maybe
型クラス
class Monad m => MonadPlus m where
モナドであって、選択と失敗を備えたもの。
メソッド
mzero :: m a
mplus
の単位元。さらに次の法則も満たすべきである:
mzero >>= f = mzero
v >> mzero = mzero
mplus :: m a -> m a -> m a
結合的な演算子。
インスタンス
instance MonadPlus []
instance MonadPlus Maybe
関数
名前付けの慣習
このライブラリの関数は次のような名前付けの慣習に従っている。
M
が後ろにつくものはクライスリ圏での関数を表す。すなわち、モナド型コンストラクタm
が関数の結果(カリー化していない形)に対して付けられ、それ以外にはつかない。よって、例としては次:
filter :: (a -> Bool) -> [a] -> [a]
filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
_
が後ろにつくものは結果の型が(m a)
から(m ())
になる。よって、例としては次:
sequence :: Monad m => [m a] -> m [a]
sequence_ :: Monad m => [m a] -> m ()
m
が先頭につくものは、すでに存在する関数をモナディックな形に一般化したものである。よって、例としては次:
sum :: Num a => [a] -> a
msum :: MonadPlus m => [m a] -> m a
Monad
の基本的な関数
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f
はsequence . map f
と同値である。
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
mapM_ f
はsequence_ . map f
と同値である。
forM :: Monad m => [a] -> (a -> m b) -> m [b]
forM
はmapM
の引数を逆にしたものである。
forM_ :: Monad m => [a] -> (a -> m b) -> m ()
forM_
はmapM_
の引数を逆にしたものである。
sequence :: Monad m => [m a] -> m [a]
各アクションを左から右に順番に評価し、結果を集める。
sequence_ :: Monad m => [m a] -> m ()
各アクションを左から右に順番に評価し、結果を無視する。
(=<<) :: Monad m => (a -> m b) -> m a -> m b
>>=
と同じで、引数が入れ替えたもの。
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
左から右へのモナドのクライスリ合成。
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
右から左へのモナドのクライスリ合成。>>=
の引数を逆にしたもの。
forever :: Monad m => m a -> m b
forever act
はアクションを無限に繰り返す。
void :: Functor f => f a -> f ()
void value
はIO
アクションの結果の値といった評価の結果を捨て、または無視する。
リストの関数の一般化
join :: Monad m => m (m a) -> m a
join
関数はモナドの従来のjoin演算子である。モナドの構造を1レベル取り除き、(束縛されている)引数をより外側のレベルへ射影するために使われる。
msum :: MonadPlus m => [m a] -> m a
リストに対するconcat
関数の一般化である。
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
リストに対するfilter
関数の一般化である。
mapAndUnzipM :: Monad m => (a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM
関数は第一引数をリストに適用し、ペアのリストを結果として返す。この関数は複雑なデータや状態変化を行うようなモナドで主に使われる。
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM
関数はzipWith
を任意のモナドに一般化したものである。
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_
はzipWithM
の拡張で、最後の結果を無視するものである。
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
foldM
関数はfoldl
に似たものであるが、結果がモナドに包まれているところが異なる。foldM
は引数であるリストを左から右に向かって走査することに注意せよ。このことは、>>
と"畳み込み関数"が可換でない場合に問題になりうる。
foldM f a1 [x1, x2, ..., xm]
==
do
a2 <- f a1 x1
a3 <- f a2 x2
...
f am xm
右から左に向かった評価が必要であれば、入力のリストを反転させればよい。
foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()
foldM
に近いが、結果を捨てる。
replicateM :: Monad m => Int -> m a -> m [a]
replicateM n act
はアクションをn
回行い、結果を集める。
replicateM_ :: Monad m => Int -> m a -> m ()
replicateM
に近いが、結果を捨てる。
モナディックな式の条件付き実行
guard :: MonadPlus m => Bool -> m ()
guard b
はb
がTrue
であればreturn ()
であり、b
がFalse
であればmzero
である。
when :: Monad m => Bool -> m () -> m ()
モナディックな式の条件付き実行である。例えば、
when debug (putStr "Debugging\n")
はブール値debug
がTrue
であれば文字列Debugging\n
を出力し、そうでなければ何もしない。
unless :: Monad m => Bool -> m () -> m ()
when
の逆である。
モナディックな持ち上げ演算子
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
関数をモナドに持ち上げる。
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
関数をモナドに持ち上げ、モナディックな引数を左から右へと走査する。例えば、
liftM2 (+) [0,1] [0,2] = [0,2,1,3]
liftM2 (+) (Just 1) Nothing = Nothing
liftM3 :: Monad m => (a1 -> a2 -> a3 -> r)
-> m a1 -> m a2 -> m a3 -> m r
関数をモナドに持ち上げ、モナディックな引数を左から右へと走査する。(liftM2
を参照)
liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r)
-> m a1 -> m a2 -> m a3 -> m a4 -> m r
関数をモナドに持ち上げ、モナディックな引数を左から右へと走査する。(liftM2
を参照)
liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r)
-> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
関数をモナドに持ち上げ、モナディックな引数を左から右へと走査する。(liftM2
を参照)
ap :: Monad m => m (a -> b) -> m a -> m b
多く場合liftM
演算子は、(関数適用を持ち上げる)ap
を使用したものに置き換えることができる。
return f ‘ap‘ x1 ‘ap‘ ... ‘ap‘ xn
は次と等しい。
liftMn f x1 x2 ... xn