【Control.Monad.Trans】(2) StateTモナド



[Haskell/Monad transformers](https://en.wikibooks.org/wiki/Haskell/Monad_transformers)
[A Gentle Introduction to Monad Transformers](https://github.com/kqr/gists/blob/master/articles/gentle-introduction-monad-transformers.md)
[モナドトランスフォーマー・ステップ・バイ・ステップ](http://bicycle1885.hatenablog.com/entry/2012/12/08/165236)

---

[【Control.Monad.Trans】(1) Identityモナド - Qiita](https://qiita.com/sand/items/e88b798d8783606071c5)
[【Control.Monad.Trans】(2) StateTモナド - Qiita](https://qiita.com/sand/items/802b8c4a8ae19f04102b)
[【Control.Monad.Trans】(3) ExceptTモナド - Qiita](https://qiita.com/sand/items/fe3c29560136803e8b11)
[【Control.Monad.Trans】(4) ReaderTモナド - Qiita](https://qiita.com/sand/items/93d6ba75b0c4e39ce295)
[【Control.Monad.Trans】(5) IOモナド - Qiita](https://qiita.com/sand/items/ee3c19c191c87c32f867)


Monad transformersを中心に、モナドの基本的な事項をまとめてみました。(1)～(5)までの連載で、Monad transformersを試行していきます。実際にはそれぞれの回で、Identity, StateT, ExceptT, ReaderT, IO モナドを積み重ねていく例題を示しています。

Monad transformersについては、以下のサイトが表向きは最新といわれるものでしょうが、中身はControl.Monad.Transの方をimportしたりしているので、説明の都合上、Control.Monad.Transを使います。
[mtl - Hackage - Haskell](https://hackage.haskell.org/package/mtl)


今回はStateTモナドです。


# 1. StateTモナドの定義

[Control.Monad.Trans.State.Strict - Hackage - Haskell](http://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-Trans-State-Strict.html)

m をbaseモナドとして、以下のようにStateT型を定義します。

```Haskell
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) } 
```

モナドとしての定義です。baseモナド m のreturnや>>=を使って以下のように定義します。

```Haskell
instance (Monad m) => Monad (StateT s m) where
    return a = StateT $ \ s -> return (a, s)

    m >>= k  = StateT $ \ s -> do
        (a, s') <- runStateT m s
        runStateT (k a) s'

    fail str = StateT $ \ _ -> fail str
```

この定義からわかるように、m >>= k の m の値は a です。(*1)
failの定義の右辺のfailは、m=Identityの場合は、Identityモナドのfailです。


# 2. 補助関数 - state, get, put

StateTモナドは通常、グローバルな状態を管理するために使われます。アクセス関数としてgetとputが定義されます。stateは純粋な状態遷移関数をStateTモナドに変換するものです。


```haskell
-- | Construct a state monad computation from a function.
-- (The inverse of 'runState'.)
state :: (Monad m)
      => (s -> (a, s))  -- ^pure state transformer
      -> StateT s m a   -- ^equivalent state-passing computation
state f = StateT (return . f)


-- | Fetch the current value of the state within the monad.
get :: (Monad m) => StateT s m s
get = state $ \ s -> (s, s)

-- | @'put' s@ sets the state within the monad to @s@.
put :: (Monad m) => s -> StateT s m ()
put s = state $ \ _ -> ((), s)
```


# 3. StateTモナドの使用例

簡単な例を2つ示します。その前に実行コマンドの簡略版を定義しておきます。

```
runState m = runIdentity . runStateT m
```

まずはgetとputの使用例です。

```Haskell
import Control.Monad.Trans.State.Strict
import Data.Functor.Identity

-- runState threeTicks 5

tick :: StateT Int Identity Int
tick = do n <- get
          put (n+1)
          return n

threeTicks :: StateT Int Identity Int
threeTicks = do n1<-tick
                n2<-tick
                n3<-tick
                return(n1+n2+n3)
```

以下のコマンドで実行します

```
*Main> runState threeTicks 5
(18,8)
```


次はStateTでスタックを実現します。stateを明示的に使う例となっています。

```Haskell
Control.Monad.Trans.State.Strict
import Data.Functor.Identity

-- runState tasu [8,7..0]

type Stack = [Int]

tasu :: StateT Stack Identity Int
tasu = do
  state $ \xs -> ((), 9:xs)       -- push 9
  a <- state $ \(x:xs) -> (x, xs) -- a <- pop
  b <- state $ \(x:xs) -> (x, xs) -- b <- pop
  return (a+b) 
```

ここで注目して欲しいのは、StateTモナドの値である a と b は、それぞれ \\(x:xs) -> (x, xs) の x の値であることです。このことは上で述べた(*1)に対応しています。

それでは実行してみましょう。

```
*Main> runState tasu [8,7..0]
(17,[7,6,5,4,3,2,1,0])
```


今回は以上となります。