モナド

11.5 モナドの構文

はまる…

do式のサンプルを作ってみたところ、見事にハマってしまいました。
こんな感じ。

  • do_example.hs
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 cs <- lookup "database" config
          print $ lookup "encoding" cs
% ghc -W -o do_example do_example.hs  

do_example.hs:8:10:
    Couldn't match expected type `Maybe b'
           against inferred type `IO ()'
    In the expression: print $ lookup "encoding" cs
    In the expression:
        do cs <- lookup "database" config
             print $ lookup "encoding" cs
    In the definition of `main':
        main = do cs <- lookup "database" config
                    print $ lookup "encoding" cs


あれれ?最後の「print $ lookup "encoding" cs」の部分で、
「IO ()」のはずが「Maybe b」にマッチしてる、と怒られてしまいます。
でも

main = print $ lookup "database" config >>= lookup "encoding"


と書くと問題ない。
???これって本書にある規則に則って書き換えただけなんだけど…。
これならいける。

main = print result

result :: Maybe String
result = do cs <- lookup "database" config
            lookup "encoding" cs


う〜ん。さらにこんな感じに書いてみます。

main = print $ do cs <- lookup "database" config
                  lookup "encoding" cs


これは問題ない。
あっ、そうか!
問題のあったコードは次のコードと等価なんですね。

main = lookup "database" config >>= print $ lookup "encoding"


これだと…

main = (lookup "database" config >>= print) $ lookup "encoding"


ということになってしまいますね。
「(lookup "database" config >>= print)」は「IO()」つまり何も返さないアクションですが、
アクションに引数として「lookup "encoding"」を渡しています。
しかもこれは引数が一つ足りないので、関数の部分適用の状態、つまり関数なわけです。
アクションに関数を渡すという暴挙を行おうとしていたわけですね。


ふぅむ…、まだまだ修行が足りませんね。