StateモナドはMonadStateになってまして、getとかputとか持ってるわけです。で、getすると状態が取れてput sすると状態がセットできる。
myCounter = do n <- get put $ n + 1 return $ n + 1 doCount3 = do myCounter myCounter myCounter countResult = evalState doCount3 0
でも、このgetとかputで使っている"カウントアップされている変数"の正体は一体なんなんでしょ? 実体が見えなくて、まるで魔法のようです。そんなわけで、軽く考えてみる。
まず、do記法ですが、こいつの正体は束縛なわけです。ってことは関数合成ですね。で、試しに(\x -> (v, y))のようなStateモナドに、getを束縛してみた。
getと束縛の定義からこんな感じですかね?
任意のxについて、(\x -> (v,y)) x = (v,y),
(\_ -> (\s -> (s,s)) v = (\s -> (s,s)),
(\s -> (s,s)) y = (y,y) なので、
(\x -> (v,y)) >>= (\_ -> (\s -> (s,s))) = (\x -> (y,y))
valueとしてステータスyを返すモナドに変わりました。これで次に束縛する関数からステータスが参照できるって仕組みですか。
同様に、これにput (n+1)を合成してみた。
(\x -> (y,y)) >>= (\n -> (\_ -> ( (), n + 1) ) ) = (\x -> ( (), y + 1) )
最初のステータスyに対して、1増加した値を返す写像となってくれた。バリューは空っぽなので、これにreturn vでバインドして値を含むようにしてみる。
return v = (\x -> (v, x) )なので、
(\x -> ( (), y + 1 )) >>= (\_ -> (\x -> (v, x) ) ) = (\x -> (v, y + 1))
最終的には、バリューはそのままでステータスが1増加したモナドが完成。getとputが利用している領域ってのは、モナドの返り値部分だったみたいですね。これらを参照・変更を繰り返すことでgetとputの機能を実現できると。で、evalStateで初期値を与えた時点で、溜め込んだこれらの処理が一気に走ると。
・・・また前みたいに間違ってたらごめんなさいw。勉強中のメモってことでご容赦をm(_ _)m。