#!/usr/bin/env stack {- stack script --resolver lts-21.7 --package mtl -} import Control.Monad.State.Strict -- `State` モナドの実装例は『すごい Haskell』 P335 などを参照 -- `do` 記法で関数を作成 example1 :: Int -> (Double, Int) example1 s0 = (`runState` s0) $ do modify (+ 1) modify (+ 1) modify (+ 1) return 0.0 -- `do` 記法を `>>=` に desugar (『すごい Haskell』 P296) example2 :: Int -> (Double, Int) example2 s0 = (`runState` s0) $ modify (+ 1) >>= \() -> modify (+ 1) >>= \() -> modify (+ 1) >>= \() -> return 0.0 -- `>>=` を展開 example3 :: Int -> (Double, Int) example3 s0 = (`runState` s0) $ state $ \s0 -> let ((), s1) = runState (modify (+ 1)) s0 in (`runState` s1) $ state $ \s1' -> let ((), s2) = runState (modify (+ 1)) s1' in (`runState` s2) $ state $ \s2' -> let ((), s3) = runState (modify (+ 1)) s2' in (`runState` s3) $ state $ \s3 -> (0.0, s3) -- `modify` を展開 example4 :: Int -> (Double, Int) example4 s0 = (`runState` s0) $ state $ \s0 -> let ((), s1) = runState (state $ \s -> ((), s + 1)) s0 in (`runState` s1) $ state $ \s1' -> let ((), s2) = runState (state $ \s -> ((), s + 1)) s1' in (`runState` s2) $ state $ \s2' -> let ((), s3) = runState (state $ \s -> ((), s + 1)) s2' in (`runState` s3) $ state $ \s3 -> (0.0, s3) main :: IO () main = do let res1 = example1 39 let res2 = example2 39 let res3 = example3 39 let res4 = example4 39 print res1 print res2 print res3 print res4