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.MaybeSystem.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

MonadFunctorのインスタンスは追加で次の法則も満たすべきである。

  • fmap f xs == xs >>= return . f

Preludeで定義されているリスト、Data.Maybe.MaybeSystem.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 fsequence . map fと同値である。

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

mapM_ fsequence_ . map fと同値である。

forM :: Monad m => [a] -> (a -> m b) -> m [b]

forMmapMの引数を逆にしたものである。

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 valueIOアクションの結果の値といった評価の結果を捨て、または無視する。

リストの関数の一般化

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 bbTrueであればreturn ()であり、bFalseであればmzeroである。

when :: Monad m => Bool -> m () -> m ()

モナディックな式の条件付き実行である。例えば、

       when debug (putStr "Debugging\n")

はブール値debugTrueであれば文字列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