コップ本のMonadに関する記述が一部不正確な件

Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版

一部不正確とは
MonadとMonadPlusを区別していなくて、witFilterメソッドの実装がMonadに対して必須のように書いてある」
ということです。


以下それの解説的なものを少し書きますが、上記の一文で意味わかる人はこれ以降読まなくていいと思います


ちょっと長くなるけど引用。第2版の450ページ

map、flatMap、withFilterは、モナドの演算として定式化できる。そうした定式化により、上に示した型を正確に持てるようになる。さらに、あらゆるモナドは、map、flatMap、withFilterの3つ、さらに「ユニット」コンストラクター(要素値からモナドを作るもの)によって特徴づけられる。

中略

map、flatMap、withFilterは、モナドという関数型概念のオブジェクト指向版と見ることができる。これらの3つのメソッドによって書き換えられるfor式は、モナドのための構文と考えることができる。

明らかに、「モナド」の部分を「モナドプラス」にするか、そうでないならwithFilterを除いたほうが正確だと思います。*1

念のため英語版*2も少し確認してみましたが

http://www.artima.com/pins1ed/for-expressions-revisited.html#23.6

訳の間違いなどではなく、英語版も同じように書かれてますね。
MonadPlusとfilterの関係は以前ちょっと書きました。

HaskellのdoとScalaのfor式とEitherとMonadPlus

これ↑ではEitherのこと話しましたが、他にもMonadとMoandPlusの違いの理解のために、
Monadにはなるけど、MonadPlusにはならない」ものを例として上げると、NonEmptyListというのがあります(標準ライブラリではなくScalazのものです、すいません)

https://github.com/scalaz/scalaz/blob/v7.0.0/core/src/main/scala/scalaz/NonEmptyList.scala

「要素を1つ以上保持している」ことが保証されることが特徴で、それ以外は普通のListと変わりません(つまり片方向リンクリスト)
証明とかではなく
「NonEmptyListがMonadPlusではない=>つまり(自然な)filterメソッドを定義できない」
ことに対する直感的な(?)説明をしてみると、

「要素を1つ以上保持していることが保証されなければならない」のに、もしfilterしていき1つも当てはまるものがなくなったらどうするの?となりますよね?(例外投げるとか?)なので、NonEmptyListはMonadですが、MonadPlusではありません。でも、for式で*3使えます。

もう一度まとめておくと、ScalaのforはflatMapとmapを正しく実装できた場合は「Monadのための記法」になりますし、それに加えてwithFilter*4を実装できれば「MonadPlusのための記法」です。

細かいことのようですが、これを区別できるとき、区別する必要があるときは、ちゃんと区別して話しましょう。

*1:ちなみに、コップ本にはこのページくらいしか「モナド」という言葉がでてこないですし、MonadPlusにいたっては一言もでてこなかったはずです

*2:英語版第一版は無料公開されてる

*3:パターンマッチやifの機能は除いて

*4:filterとシグネチャ同じですが、とある事情によりwithFilterになってますが、そのあたりは説明面倒なのでググってください