今回は、前回読んでいた第14章の後半を読みました。モナディック関数(モナド値を扱う関数)やモナドの作り方を扱っていました。
14.5 便利なモナディック関数特集
このセクションは意外と内容が多いです。
liftM
は fmap
のモナド版。liftM
自体が重要というよりも、モナドがファンクターの性質を内包しているという点が重要な印象を受けました。同様に ap
の話も、モナドがアプリカティブファンクターの性質を内包しているという点が重要と思いました。ただ、どうやら GHC の最新版では、モナドは実際にファンクターやアプリカティブファンクターでなくてはならないという制約がついたらしいです。
join
はモナドをひとつ外します。リストに対して使うと concat
と同等。ほかの言語だと flatten
とかの名前で呼ばれたりする気がします。join
が大事なのは納得できる話ですが、なぜモナドじゃないと join
が定義できないのかという点はまだあんまり腑に落ちてない感じです。
filterM
は filter
関数のモナド版。foldM
は foldl
関数のモナド版。これらが重要だというのは、まあそうだろうと感じます。
14.6 安全な逆ポーランド記法電卓を作ろう
モナディック関数の活用例。この本は、こういった具体例が豊富な点が良いと思います。
逆ポーランド記法電卓は第10章で作成していましたが、不正な入力があると落ちてしまうというものでした。これに対して、Maybe
モナドを導入することで正常に計算できれば Just
値、エラーなら Nothing
という振る舞いをするようにします。
振り返っていて思いましたが、Maybe
だとエラー時に Nothing
だけで分かりにくいので、Either
でエラー内容を返したり、Writer
でログを残したりするほうが良いような気がします(これちょっとした練習問題になりますね)。
14.7 モナディック関数の合成
<=<
はモナディック関数の合成。余談ですが、Haskell はこういう記号を連ねた謎の演算子が多い印象があります。このへんは正直苦手。
第13章で作成した騎士の旅のプログラムを、手数を引数で与えられるように改造できるようになりました。
14.8 モナドを作る
モナドをいつ作るかというのは疑問のひとつでしたが、このセクションの最初にその点について記述がありました。普通、モナドは作りたいと思って作るものではなく、作った型が文脈つきの値を表現していると気づいたらモナドにする、ということのようです。なるほど。
モナドを作るときに大変なのが、>>=
演算子の定義のようです。これは、m >>= f
と join (fmap f m)
が同じであることを使うのが良いとのこと。まず join
にあたるものをまず定義して、それを使って >>=
を定義してしまえばよいわけですね。
余談。読書会でもちょっと話が出ましたが、普通のコイン2枚とイカサマコイン1枚を投げたときの確率の話で、「3枚とも裏が出る確率は9/40です。これは25パーセントより少ないですね」と唐突に書かれています。この直前に「イカサマコインが紛れ込んでいるとはいえ3枚とも裏が出る確率っていうのがいうほど大きくはないってことが分かります」とあるので、直感より低い確率だということを言いたかったのだと思います。でも、普通のコインで2枚とも裏が出る確率が25パーセントなんだから、それより少ないのは直感的にも当たり前の話なわけで・・・。まあ、細かいところへのツッコミはこのへんで。
次回は最終回
いよいよ次回は感動の最終回です。
すごいHaskell読書会 in 大阪 by iseebi によると、2週目の第1回は2014年1月でした。1年半かかってここまで来たわけですね。さらにこの読書会の最初は2012年11月だったそうなので、2年半以上経っていることになりますね。すばらしいです。