アナログ金木犀

つれづれなるまままにつれづれする

モナドがなんとなくわかった気がするような気がする

すごいH本を読みました。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

感想というより、モナドの理解をつらつら書いてみます。

すべて自分の理解なので、間違ってるところ指摘いただけたらありがたいです。

モナドの定義

下記を満たせばモナドです。

  1. (return x) >>= f == f x
  2. m >>= return == m
  3. (m >>= f) >>= g == m >>= (\x -> f x >>= g)

(きっとここで多くの人が離脱する。。。というか、読む前の自分だったらそうだな。。)

xはただの値、fは関数です。fxっていうのは関数fに引数xを渡す意味です。

mはモナド値です。モナド値ってのは文脈付きの型です。

return xはmになります。

>>= は関数です。bindっていうのかな。

結構これが肝なのですが、右の関数を受け取って左のモナド値(m)が内包している値(x)に作用させる感じ。

なんで肝かっていうと、これさえ満たしていれば良くて、右の関数を受け取って左の関数が内包している値(x)を作用させるついでに副作用を実行させることができるからです。

副作用を実行させなくても定義上は外れないので、「ついで」という表現を使っています。

例を考える

たとえば「足し算されるたびに内部のカウンターが+1される」という文脈を持ったモナドを考えます。

その時、bindという関数は足し算するついでに「カウンターを+1」します。

そうすることで下記のようなことが可能になります。

  1. (モナドな1)に 3を足す処理をbindすると、(モナドな4)になり内部のカウンターがカウントアップして1になる。

  2. その(モナドな4)に5を足す処理をbindすると、(モナドな9)になり内部のカウンターがカウントアップして2になる。

モナドのメリット

モナドのメリットってなにかというと、副作用を意識しなくて良くなることだと想いました。

たとえば、先の例で、本来行いたい処理を黒太字、副作用を青太字にするとこうなります。

  1. (モナドな1)に 3を足す処理をbindすると、(モナドな4)になり内部のカウンターがカウントアップして1になる

  2. その(モナドな4)に5を足す処理をbindすると、(モナドな9)になり内部のカウンターがカウントアップして2になる

大事なのは青文字部分はbindの定義に含まれているということです。

そのため、僕らがこのモナドを使う場合には黒文字部分だけ、つまり本来行いたい処理だけを記述することになります

これがモナドの一番のメリットなのかなと思いました。

とはいえ

まだまだ理解が浅い。

どれだけ理解してるかの確認の意味も含めて文字にしてみたけど、まだまだ厳しいかなぁという感じでした。

やっぱり実際に使ってみないと。ということで次はScala行きます。