2012年6月27日水曜日

Stateもなど

Stateモナドの有用性を考えるために書いてみます。


Rangeオブジェクトはカーソルが指すNodeとoffsetを持っています。
getRangeは現在のRangeを返すものとします。
moveはそのRangeにカーソル移動するものとします。
nextNodeとprevNodeはそれぞれ次のNodeと前のNodeを返します。

getRange,nextNode,prevNode,moveは擬似的なものなので、定義は気にしないで下さい。
この4つの関数は参照透過とかそんなわけないのでIOを返します。

これらに対して、4方向にカーソルを動かす関数を定義します。


IOはモナドなのでforが使えます。
predとsuccはscalaz.Enumのシンタックスでデクリメントとインクリメントのようなものです。

実際には移動するときに、offsetなどを調べるものですが、OptionT[IO, Unit]などと複雑になるので省略します。
これらの関数を組み合わせてみます。


さて、これらの関数、ちょっと冗長ですね。
いちいちmoveを実行しているところもいただけません。

これらをStateを使って書きなおしてみます。


squaredは値をペアにして返します。

同じように、合成したStateとそれを使って移動する関数を定義します。


getRangeとmoveの呼び出しは1回で済むようになりました。
movemovemoveというStateを使い回すことも出来ます。

さらに、Stateモナドであることを活かして、次のようなStateを定義することが出来ます。


移動した直後の状態を扱えるのがStateモナドの利点ですね。



最近は大学生がなかなか忙しいです。
俺、定期試験が終わったらScalaz勉強会開くんだ・・・・・

※追記

Intを返すようなStateになってしまうけど、Lensを使ってみても面白いかも。

0 件のコメント:

コメントを投稿