モナドの可換性(commutative)とモナドの合成
厳密に言うと質問というか確認したいことが2つ(か3つ)あるのですが、かなり関連することなので、まとめて書きます、ご了承ください。
以下のような経緯で、scalaz.ListT
(Listのモナドトランスフォーマー)が、Haskellの標準のものと同じく間違っていることが発覚しました
(本当は以前から知ってる人はいたのかも知れませんが)
とりあえずissueを作り
「同型のStreamTが存在して、そちらは正しいので、ListTは消せばいいのでは?」という意見がでました。
(個人的に消すこと自体にはそれほど反対でもないのですが)、それとは別に、現状のListTは間違ってるとはいえ、パフォーマンス面で有利な点がありそうなので、
「ListT自体はあまり変えずに、可換な場合のみListTの使用を許可するように、新しい型クラスを作ればいいのでは?」
そうした場合、Haskellのwikiに可換なモナドの説明として、以下の2つが同じなら可換なモナド
do
a <- actA
b <- actB
m a b
do
b <- actB
a <- actA
m a b
という説明がありますが、
https://wiki.haskell.org/Monad
Haskellやscalazの間違った
ListT
が要求する"可換なモナド"とは、上記のコードで必要十分条件でしょうか?(制約が、強すぎない? or 弱すぎない?)もし必要十分条件でないのなら、どのような条件が足りないか(or もっと弱めるにはどうすればいいか?)を、(できれば)具体的なHaskell(もしくはscalaz)のコードで示してもらいたいです。
というのが1つ目(と2つ目)の質問です。
また、もし上記の方針でscalazに可換なモナドの型クラスを新規に追加するとなると、
(可換 or 可換でない)モナド同士を合成した場合に
- 合成後のモナドは、どういう条件がそろえば可換になるのか?
を考えないといけなくなりますが、そのあたりがある程度簡単に説明できそうなら教えてもらいたいです(もし長くなりそうだったり、ここに書くのは難しそうなら、参考文献を教えてもらえると助かります)
以上、よろしくお願いします。