Stateモナドを手で展開してみる
30分プログラム、その392。Stateモナドを理解するために手で展開してみた。
展開してみた感想は、確かにStateモナドが状態を持てる理由は分かった気がする。でも、これをモナドに押し込めた人は天才だと思う。
do 記法
とりあえず、普通に書いてみた。
import Control.Monad.State inc :: State Int String inc = do x <- get put $ x+1 return $ show x f = fst $ runState (do a <- inc b <- inc c <- inc return (a,b,c)) 0
実行例:
*Main> f (("0","1","2"),3)
>>=を使って書き直し
do記法は書きやすいけど、展開しずらい。なのでとりあえず、>>=を使って展開する。あえて>>は使わない。
import Control.Monad.State inc2 :: State Int String inc2 = get >>= \x -> put (x + 1) >>= \_ -> return (show x) g = runState (inc >>= \a -> inc >>= \b -> inc >>= \c -> return (a,b,c)) 0
全部自分の手で書き直した
定義を参考にして、手で展開してみた。そうとう大変だった。
どこか間違ってるかも。
get' s = (s,s) put' s _ = ((),s) return' a = \s -> (a,s) inc3 :: Int -> (String,Int) inc3 state = let (v,s') = get' state in (f v) s' where f x s = let (_,s') = put' (x+1) s in (return' (show x)) s' h state = let (a,s1) = inc3 state in (\s -> let (b,s2) = inc3 s in (\s -> let (c,s3) = inc3 s in (return' (a,b,c)) s3) s2) s1