Haskellのモナド(7)
前回までの説明で、おそらく>>=演算子とreturnが、Maybeを使ったコードを書くときに、煩雑なコードから解放されるために有益であると同意してもらえると思います。これがどうして動くのか、そしてこれが何を意味しているのかを考えましょう。
その説明のために、以下の様なコードを書きました。
bothGrandfathers p = do { f <- father p; gf <- father f; m <- mother p; gm <- father m; return (gf, gm); }
このコードが命令型言語のコードの断片に見えたとしたら、それは正しいです。とりわけ、この命令型言語は例外処理をサポートしています。例えば、もし例外が起きたら、doブロック全体が失敗し、例外として終了します。
言い換えれば、father pという式は、Maybe Personという型をもちますが、Person型を結果として返す命令型言語の式として翻訳されます。これはすべてのモナドにおいて行われます。M a型の値はa型を返す値として翻訳されるということです。そしてこれらはモナドMを拾って文脈から類推されます。
(>>=)演算子はセミコロンの関数版です。let式が、
let (x = foo) bar <===> (¥x -> bar) foo
のように関数で表せるように、変数宣言とセミコロンは>>=演算子として表すことが出来ます。
x <- foo; bar <===> foo >>= (¥x -> bar)
関数returnはaという値をM aという命令型言語のレベルにまで持ち上げます。
異なる意味をもつものはそれぞれ異なるモナドに対応します。
意味 | モナド |
---|---|
例外(匿名) | Maybe |
例外(エラー情報付き) | Error |
状態 | State |
入出力 | IO |
非決定性 | [](リスト) |
環境 | Reader |
ログ | Writer |
更にいうと、それぞれは単独で実行されることより、複数の異なるものと一緒に利用されることが多いです。そのため、モナドトランスフォーマが必要となります。