モナド
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"」を渡しています。
しかもこれは引数が一つ足りないので、関数の部分適用の状態、つまり関数なわけです。
アクションに関数を渡すという暴挙を行おうとしていたわけですね。
ふぅむ…、まだまだ修行が足りませんね。