FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

モナド(clojure.algo.monads)よくわからないからとりあえずいじってみた

こんにちわ、k_imaizumiです。

関数型の言語の情報を見てるとよく目にするモナド。 なんかこいつを説明するためにいろんな記事がわんさかありますが、結局よくわからない。 すごいHaskellたのしく学ぼう!を読むも難しくてよくわからない。

よくわからなすぎて手がでないままってのもアレだなぁということでとりあえずいじってみたってのが今回の記事です。 HaskellだとHaskellそのものの理解がアレなので今回はclojureでいじることにしました。

なんかライブラリがあるそうなのでこれをつかってみました。 github.com

なんかモナドってうんたらモナドってな感じで種類があるそうです stateとかmaybeなんかは名前は聞いたことある感じです

サンプルコードを見るとstateの方は読むの嫌になる感じですが、maybeの方は分かりやすかったんで、これみながら適当にいじってみることにしました。

algo.monads/monads.clj at algo.monads-0.1.5 · clojure/algo.monads · GitHub

ここはmaybe-mに関数を定義してるようですね、2が定義する関数の引数で演算子が実行される処理の関数な感じでしょうか。 この次はここで定義した関数を実際使わないで割り算定義しに行っちゃってるのが、私の頭からすると早すぎて追いつけないので自分で使って見ることにします。

といっても使い方がよくわからんというのがあったのですが、割り算をよく見返すとなんかdomonadでモナドつかって計算するみたいなノリに見えるのでこいつをちょいといじって定義したのをためしてみました。

f:id:k_imaizumi:20150818160322p:plain

普通に計算できました。んでもこれだけじゃ何が嬉しいのか全然わからないですね。maybe-mは計算途中でnilが入った時にnilを返してくれるものと書かれてたのでnilを入れたmaybe-mと普通の演算にnil入れたので比較してみました。

f:id:k_imaizumi:20150818162024p:plain

meybe-mを使った方はnilが返り、普通に計算したのはぬるぽってますね。なんかこれくらいなら使えそうな気がします。 あと試しに文字とか入れてみました。

f:id:k_imaizumi:20150819102245p:plain

途中でnilがあった場合はnilが優先されますが、型が合わないと普通にClassCastExceptionが発生しました。

some-functionまではなるほどねぇっと読めたのですが、m-plusがよくわからない。渡された関数の評価値がnilでない最初の値を返すっていう動きは理解できたけど、それで何が嬉しいのとかがまだ全然わからない。

他にテストやサンプルみて他のモナドいじってましたがwriter-mは分かりやすいし使いやすそうでした。

f:id:k_imaizumi:20150818194749p:plain

計算結果の他にwriteで追加していった文字列も一緒に返してくれる。これはいろんなところで使い道ありそうですね。 m-resultで値を設定して処理したい関数を呼べばよさそうなので使うもの簡単そうですし。

ここでようやく、これマクロ展開したらどうなってるだろうと思いちょいと見てみると f:id:k_imaizumi:20150818202419p:plain

こんな感じになってました。m-bindの引数の関数でひたすら処理をぶら下げてる感じなんですね。 m-bindの第一引数で二つ目の返り値の設定やm-resultの呼び出しを、二つ目引数でm-resultを呼び出した際の値を関数の引数に設定して使えるようにする。といった感じでしょうか。なんとなくなイメージがつきました。あと括弧がカラフルで綺麗ですね。

reader-mはテストが分かりやすかったものの、どう使えばいいのかあまりイメージが沸かず。 sequence-mはforと同じノリですね。なんとなく書き方が同じ感じで、違う問題を解決できるのがいい感じなのかなぁとかぼんやり思いました。

state-mは大変そうなのでまたそのうち... そんなこんなで、今回はモナドが何かよくわからんので適当にいじってみたというお話でした。