再・モナドについて勉強したことの整理

## モナド・・
そもそも[すごいHaskellたのしく学ぼう!](http://www.amazon.co.jp/すごいHaskellたのしく学ぼう-Miran-Lipovača/dp/4274068854)を読む動機となったキーワード。[関数プログラミング実践入門](http://www.amazon.co.jp/%E9%96%A2%E6%95%B0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E2%94%80%E2%94%80%E7%B0%A1%E6%BD%94%E3%81%A7%E3%80%81%E6%AD%A3%E3%81%97%E3%81%84%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%9F%E3%82%81%E3%81%AB-WEB-PRESS-plus/dp/4774169269)を読むだけではまだまだ概念を捉えきれず、理解できなかった。

学ぶうちにモナドは型クラスであり、関連する型クラスとして `Functor` 、`Applicative` があることを知った。全体として、それぞれの型クラスができることとの差異を整理することでモナドの必要性やその位置付けの整理に役立てたいと考えている。

##モナドを使う動機
Haskell では、**ある型 `a` をとって、 `a` を返す関数** は、その関数を続けざまに使用することができる。

```hs:Intを２つとって、Intを返す関数の例
func :: Int -> Int -> Int
func 3 (func 4 (func 5 ・・・ といったように続けざまに使用できる
```

また、もし**結果が失敗するかもしれないような計算をする関数**の場合は返り値の型を `Maybe a` のようにしておきたい。

> 例えば、あるリストに要素 x が含まれているかどうかを調べ、含まれていればその要素を、含まれていなければ `Nothing` を返すような関数のこと。単純に`Bool`値 を返す関数よりも利用できる範囲が広がるだろう。

この考えは自然なので、最初の`func` にこの文脈を取り入れることにする。すると、**型 `a` をとって型 `Maybe a` を返す関数**となり、続けざまに使用することはできなくなってしまう。

```hs
func :: Int -> Int -> Maybe Int
func 3 (func 4 (func 5 ・・・ といったように続けざまに使用できない！
```

有効な値がある以上は続けざまに使えると便利な関数なので、**引数と返り値の型はちょっと違うけれどなんとか実現できないか**？

これに答えてくれるのがモナドということになる。

```hs:答えてくれた結果
(Just 3) >>= func 4 >>= func 5 >>= ・・・ bind演算子を使って実現できた！
```

## モナドの一般的な概要
モナドは、**計算する上で生まれる特定の文脈を効率的に扱うための仕掛け** を実現するためにある。一般的な概要については次のリンクにまとめています。

* [モナドについて勉強したことの整理](http://qiita.com/rooooomania/items/5c0dd9d8551d48aaf9b3)

## bind 演算子
先述した要求に応えてくれる演算子として、`>>=` ( bind 演算子 )がある。

> 引数と返り値の型はちょっと違うけれどなんとか実現できないか？という要求

`Maybe` モナドの実装を例に見てみると、

```hs
instance  Monad Maybe  where
    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing

    (Just _) >>  k      = k
    Nothing  >>  _      = Nothing

    return              = Just
    fail _              = Nothing
```

有効な値を引数にとって、第２引数( 右辺 )の関数を適用している。また、第１引数( 左辺 )が無効値だったら、結果も無効な値としている。
bind 演算子の型は`(>>=) :: m a -> (a -> m b) -> m b` なので、次のように書ける。

```hs
Just 3 >>= \x -> return (x + 5) >>= \x -> return (x * x) -- Just 64
```

ちなみに、`Functor` 型クラスや `Applicative` 型クラスのインスタンスではこのように**内部の値同士が相互作用するような操作**は難しい。

## Functor/Applicative/Monad
文脈を持った計算を行うために、`Functor` 、 `Applicative` 、`Monad` という型クラスがある。より柔軟にこの計算を行える（≒強化版）という概念を**<** で表すと、**`Functor` < `Applicative` < `Monad`**ということになる。

それぞれの型クラスについての概要は次のページにまとめています。

* [ファンクターについて勉強したことの整理](http://qiita.com/rooooomania/items/fe8f7a4eca8acd718000)
* [アプリカティブファンクターについて勉強したことの整理](http://qiita.com/rooooomania/items/93b689f481999f25b9ab)
* [関数もアプリカティブ](http://qiita.com/rooooomania/items/c63f03ef3fe20ef92667)

これらの型クラスを、特徴、できること、できないことの３つで比較したマトリクスが下表となる。

|型クラス|特徴|できること|できないこと|
|---|---|---|---|
|Functor|文脈付きの値に普通の関数を適用する|`fmap` で普通の関数を文脈付きの関数に lifting する[1]|fmap された関数を文脈付きの値に簡単に適用する方法がない|
|Applicative|文脈付きの値に普通の関数（または普通の関数を文脈付きの関数に持ち上げた関数）を適用する|アプリカティブ・スタイルを使って文脈を維持しながら普通の関数を適用する[2]|アプリカティブ・スタイルでは、ある文脈付きの値が他の文脈付きの値に依存するような操作の記述が難しい|
|Monad|**文脈付きの値に、普通の値をとって、文脈付きの値を返す関数**を適用する<br>bind演算子をサポートしたアプリカティブ・ファンクター|bind演算子で文脈付きの値同士が相互作用するような操作を行う|---|

> 普通の関数： 普通の値をとって、普通の値を返す関数（普通でない ≒ リストや`Maybe` などの文脈付きの値 )




[1]:http://qiita.com/rooooomania/items/fe8f7a4eca8acd718000#fmap-のまとめ

[2]:http://qiita.com/rooooomania/items/93b689f481999f25b9ab#アプリカティブスタイル



## モナド型クラスのインスタンス

主要なインスタンスについては、
* [モナドについて勉強したことの整理（個別モナド）](http://qiita.com/rooooomania/items/4b5b0a5b184e006dc7e2) に整理しています。

## MonadPlusとguard関数

まず、`MonadPlus` 型クラス定義には次にようにある。

```hs
-- The MonadPlus class definition

-- | Monads that also support choice and failure.
class Monad m => MonadPlus m where
   -- | the identity of 'mplus'.  It should also satisfy the equations
   --
   -- > mzero >>= f  =  mzero
   -- > v >> mzero   =  mzero
   --
   mzero :: m a 
   -- | an associative operation
   mplus :: m a -> m a -> m a
```

> モナドは、選別と失敗もサポートしていて、 `MonadPlus` のインスタンスになればその恩恵を受けられるということだろう。

`MonadPlus` は、モノイドの性質を併せ持つモナドを表す型クラス。リスト`[]` も `MonadPlus` のインスタンスになれる。

```hs
instance MonadPlus [] where
   mzero = []
   mplus = (++)

instance MonadPlus Maybe where
   mzero = Nothing

   Nothing `mplus` ys  = ys
   xs      `mplus` _ys = xs
```

また、`guard` 関数がある。これは `Bool` 値をとって、空タプルを最小限の文脈に包むか、`mzero` を返す。

```hs
-- | @'guard' b@ is @'return' ()@ if @b@ is 'True',
-- and 'mzero' if @b@ is 'False'.
guard           :: (MonadPlus m) => Bool -> m ()
guard True      =  return ()
guard False     =  mzero
```

`False` が渡ってくると `mzero` を返している。つまり、`mzero` は **失敗を意味するモナド値** となる。また、引数には通常、条件式が渡され、その真偽値によって結果が **選別されることになる**。

`guard` 関数は、モナド値を扱った計算なのでdo記法で記述することができる。

```hs
sevensOnly :: [Int]
sevensOnly = do
    x <- [0..50]
    guard ('7' `elem` show x) -- 要素に文字7が含まれているかどうか
    return x --[7,17,27,37,47]
```


このとき、最後の `return x` を忘れてしまうと `guard` 関数の返り値 `[()]` が結果となってしまうので注意する。