参照:
- http://d.hatena.ne.jp/m-hiyama/20090801/1249088692
- http://d.hatena.ne.jp/bonotake/20090730/1248961849
以下メモ。
スタンピング・モナド
Haskellで一番スタンピング・モナドっぽいのは、Writerモナドかなーと思いました*1。というのは、
計算のタイプ: 計算された値にとは別にデータのストリームを生成する計算
とかありますが、生成ストリームのところがモノイドで定義されるので。
newtype Writer w a = Writer {runWriter :: (a, w)} instance (Monoid w) => Monad (Writer w) where return a = Writer (a, mempty) m >>= k = Writer $ let (a, w) = runWriter m (b, w') = runWriter (k a) in (b, w `mappend` w')
ここで、memptyはモノイドの単位、mappendはモノイドの乗算(名前は加算だけど)。タプルを作って、第一要素は普通の計算結果を、第二要素はモノイドの乗算の結果を返しています。
昔、しりとりモナドってのをこのWriterモナドで書いてみました。あんまりうまく書けた気がしてないのですが、一応参照しときます。
モナドに0をぶちこむ
などという質問をしてみたのは、やっぱりHaskellのモナドを考えていたからで。Haskellのモナドって、いわゆる数学のモナド的な演算のほかに"fail"って関数を用意してて、要は例外によるエスケープ機構が別途くっついてるんですよね。
もしかしたら、0ぶち込んだらfailしてくれたりしないかなー、あれもしかして、Haskellのモナドってただのモナドじゃなくて、0に対する演算を足したりしてる?? とかイイカゲンな妄想をしていたんですが。
そしたらまぁ、たまたま(本当にたまたま)例外モナド(HaskellでいうMaybeモナド)の話になって、妄想はやはり妄想だったことが確認されつつ妙に納得されたのでありました。めでたしめでたし。
ちなみに、後から見ると
fail 関数は、モナドの数学的定義においても要請されている 部分ではありません。
だそうですwww
…がまぁ、Haksellのモナドは明示的に定義されるモナド以外に、例外モナドが裏で標準装備されてるんだ*2とも考えられなくもない、ってまたいい加減なこと書いてるかもしれませんが。
ちなみに、Maybeモナドはこの裏表が完全に一致します。