モナド

11.2 Maybeモナド

ちょっと復習

前回、関数がMaybe a型戻り値を返すことで続く関数を実行しないことが可能と書きました。
まぁ、模式的に書くとこんな感じ。

func a -> Maybe a -> Maybe a
func a Nothing  = Nothing
func a (Just b) = 何らかの計算結果を返す

func 1 $ func 2 $ func 3 $ func 4 何らかの引数


funcを摘要する途中で計算結果がNothingになってしまったら、
それ以降の関数適用では、何もせずにNothingを返すようになります。

(>>=)とreturnについて

これをもっと分かりやすく記述するための演算子が(>>=)です。
本文の例に真似て、サンプルを作ってみました。

config :: [(String, [(String, String)])]
config = [
 ("database",  [("path", "/var/app/db"), ("encoding", "euc-jp")]),
 ("urlmapper", [("cgiurl", "/app"), ("rewrite", "True")]),
 ("template",  [("path", "/var/app/template")])]

main = do print $ lookup "database" config
          -- ベタにcase文でパターンマッチ
          print $ case (lookup "database" config) of
                    Just entries -> lookup "encoding" entries
                    Nothing      -> Nothing
          -- Maybeモナドパイプラインで記述[1]
          print $ lookup "database" config >>= lookup "encoding"
          -- Maybeモナドパイプラインで記述[2]
          print $ return config >>= lookup "urlmapper" >>= lookup "rewrite"
          -- Maybeパイプライン途中でNothingになる例
          print $ return config >>= lookup "nothing" >>= lookup "path"


return関数は、最初その意味がよく分かりませんでしたが、こうやって書いてみると、
まさしくMaybeパイプラインにMaybe型じゃない値を潜り込ませるのに使うのがよく分かります。

分からないなりにまとめると…

う〜ん、難しい。油断すると見失ってしまいそうです。
今の時点での私の理解はこんな感じ。


Monadクラスとは、以下のクラスメソッドを持つ。

  • (>>=)

 bind。Monadモナドのパイプラインをつなぐ演算子
 パイプラインの途中でNothingになったら、パイプラインは中断される。

  • return

 Monadクラスでない型の値をMonadクラスの型の値にするための関数。
 Monadパイプラインに非Monadクラスの型の値を潜り込ませるために利用する。


う〜ん、「分かった」と言いたいんですが、やっぱり分からない。
一つ一つの内容は理解出来るんですが、全体として咀嚼出来ない感じです。
とぉっても嫌な感じです(笑)。


次はリストモナドです。頑張って付いていきます。