70084


世の中にはモナド則というものがあるようです。

[The monad laws](https://www.sampou.org/haskell/a-a-monads/html/laws.html)
から引用します。

>
[code]

>     (return x) >>= f == f x
>     m >>= return == m
>     (m >>= f) >>= g == m >>= (\x -> f x >>= g)
>  
[/code]

さてこれを満たすために下記のようなコードを書いて練習しました。

コード説明: `MayNull`は自作の`Maybe`のようなもの。`MyMonad`は自作の`Monad`のようなものです。本来のHaskellにある
`>>=` は 自作版では `>>>>>`, `return` は自作版では `rrrrr`
に置き換えてあります。（[この質問](https://ja.stackoverflow.com/questions/70043/monad%E3%81%AEm%E3%82%84functor%E3%81%AEf%E3%81%8C%E4%BD%95%E3%82%92%E3%81%95%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84-%E3%81%9D%E3%81%97%E3%81%A6-instance-%E5%81%B4%E3%81%AE%E8%A8%98%E6%B3%95%E3%82%82%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84)の回答例なども参考にしています）

[code]

    f x = Have (x + 1)  -- 1増やす
    g x = Have (x * 2)  -- 2倍にする
    
    data MayNull a = Have a | Null deriving Show
    
    class MyMonad m where
      (>>>>>) :: m a -> (a -> m b) -> m b
      rrrrr :: a -> m a
    
    instance MyMonad MayNull where
        (Have x) >>>>> f = f x
        Null >>>>> _ = Null
        rrrrr = Have
    
[/code]

上記が定義と実装部で下記がモナド則が実際に成り立っているのを試したコードです。

[code]

    -- 左恒等性確認
    -- (return x) >>= f == f x
    rrrrr 3 >>>>> f   -- Have 4
    f 3               -- Have 4
    
    -- 右恒等性
    -- m >>= return == m
    (Have 3) >>>>> rrrrr -- Have 3
    Have 3               -- Have 3
    
    -- 結合法則
    -- (m >>= f) >>= g == m >>= (\x -> f x >>= g)
    (Have 3 >>>>> f) >>>>> g          -- Have 8
    Have 3 >>>>> (\x -> f x >>>>> g)  -- Have 8
    
[/code]

# 質問

これは、`Maybe`と`Monad`を模倣したものなので、モナド則が保たれているわけですが、この状態からどこかを書き換えるとモナド則をくずせるものなのでしょうか？

本来であれば `Applicative` のインスタンスである必要もあるようですが、３つの法則とは関係ないと考えています。

まだ模倣の通りしか使っていくことができず、普通にプログラムを書いていったときに、どのようなタイミングでモナド則を崩してしまうのかしりたいと思っています。

つまりどこの部分にどのように注意してコードを書けばいいのかというようなことが気になっています。おそらく、`instance`を実装しているときですよね？

`instance`の実装さえミスがなければ `f`や`g` はモナド則を満たさなくなってしまうことと関係ないと思っているのですがいかがでしょうか？


CC BY-SA 4.0
2020-09-02T08:15:59.857
70079
2020-12-25T00:46:57.777
9008
question
haskell
モナド則を崩してしまう例が知りたい


`return x = Null` にしてしまうとか、`(Have x) >>>>> f = Null`
にしてしまうとか、とにかく型があってさえいれば実装は色々できてしまうことを考えると壊れる例が作れます。

モナド則の良いところは、この規則を満たすように書いてしまえば後は様々な "モナド的な" 操作を気にせずに行えるところにあります。具体的には do
記法などです。それで良いことが（一定の仮定のもとで）証明できます。というより、モナド則から証明できることが "モナド的な"
操作として知られている、といった方が近いですが。

ただし、ある型に対して、モナド則を満たすような instance
の定義はひとつではないことには注意が必要です。少しややこしいので詳細は書きませんが、たとえばリストのモナドはいくつかの instance
を考えることができます。


CC BY-SA 4.0
2020-09-02T11:30:40.647
70084
2020-09-02T11:30:40.647
19110
70079
answer


すみません、補足記事を書いていたら非常に遅くなってしまいましたが、コメントにも回答にも明確に回答されてないとおぼしき部分について回答させてください。

> つまりどこの部分にどのように注意してコードを書けばいいのかというようなことが気になっています。おそらく、instanceを実装しているときですよね？
>
> instanceの実装さえミスがなければ fやg はモナド則を満たさなくなってしまうことと関係ないと思っているのですがいかがでしょうか？

ご認識のとおりです。  
Monad則はあくまでも`>>=`や`return`についての規則であるため、`>>=`や`return`の **引数が**
、つまり`f`や`g`がどうなっていようと関係ありません。が、そもそもあなたが自分でMonadのインスタンスを定義する必要さえないので、その心配自体が杞憂だと思います。

世の中には無数のMonadが存在するように見えるかも知れません（し、広い意味のモナドは実際そうなのでしょうが）、Haskellプログラミングにおいて役に立つMonadは、数えるほどしかありません。  
実際のところ[モナドの六つの系統[Functor x Functor] -
モナドとわたしとコモナド](http://fumieval.hatenablog.com/entry/2013/06/05/182316)という記事にあるものが概ねすべてです（分類方法そのものは一般的ではないですが）。世に広まるパッケージ見ていると、一見先ほどの記事にリストアップされていないMonadが見つかることがあります。ところがそれらはほぼ間違いなく、ここにリストアップされているMonadの単純なラッパーか、それらを組み合わせて別の名前を付けたり、何らかの用途に特殊化したものです。  
独自に定義しているものがあったとしたら、それは恐らく効率のためであって、実質的な役割は先ほどの記事にリストアップされたMonadのうち、どれかに当てはまるはずです。もしリストアップされているものにどれにも当てはまらないものができれば、別途論文が書かれていると思います（というのも、実は「どれにも当てはまらない」のかどうか個人的にわからない[Select
Monad](http://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-
Monad-Trans-Select.html)というのがあるからです）。

とにかく、「Haskellプログラミングに役に立つMonad型クラスのインスタンス」というのはそれぐらい貴重なのです。（もっと広い意味の、本来の圏論における「モナド」はいろいろあるかも知れませんが、私は圏論には詳しくないのでその点は突っ込まないでください！）

少し話がそれましたが、そうした事情があるため、「モナド則を守れているかどうか」というのを意識する必要があるのは、少なくともそうしたライブラリーを作るようになったら、であって、純粋にMonadのユーザーである限りその必要はありません。

それはほとんどのHaskellプログラマーが経験しないことのはずです。  
仮に経験したとしても、多分にそれは（先ほど触れたような）既存のMonadを元に独自定義する場合であって、大抵はコピペと少しの修正で済むでしょう。  
DRY原則に従うなら、極力そんなことしたくないですよね？

それと、参考までにモナド則を破る例と、モナド則を破ったらどうなるのかについて、具体的な例を補足記事として書きましたので、良ければこちらもご覧ください。

[Writer Monadで気軽にMonad則を破る - Haskell-
jp](https://haskell.jp/blog/posts/2020/break-monad-law-with-writer.html)


CC BY-SA 4.0
2020-12-25T00:46:57.777
72873
2020-12-25T00:46:57.777
8007
70079
answer