学習の素材は、
すごいHaskellたのしく学ぼう!
State
モナドについて学んでいた時に気付いたこと。教材には、
newtype State s a = State { runState :: \s -> (a, s) }
という形で状態付き計算を包んだnewtype
を提供しているとあるが、それが hackage のソースコードを覗いても見当たらない。代わりに、次のような定義があった。
type State s = StateT s Identity
また、State
モナドはMonadState
のインスタンスでもあるらしい。それゆえ、便利な関数get
、 put
を使えるということだ。
ふーむ。これらは一体なんだろう、調べてみよう。というのが今回の記事の内容となる。
前述の newtype
がどこにあるのか、相変わらず探しているのでご存知の方がいらしたら教えてくださいm(_ _)m。
定義
関連しそうな定義をざっと表しておく。
newtype StateT s (m :: * -> *) a
= StateT {runStateT :: s -> m (a, s)}
type State s = StateT s Identity
-- | Minimal definition is either both of @get@ and @put@ or just @state@
class Monad m => MonadState s m | m -> s where
-- | Return the state from the internals of the monad.
get :: m s
get = state (\s -> (s, s))
-- | Replace the state inside the monad.
put :: s -> m ()
put s = state (\_ -> ((), s))
-- | Embed a simple state action into the monad.
state :: (s -> (a, s)) -> m a
state f = do
s <- get
let ~(a, s') = f s
put s'
return a
Monad m => MonadState s (StateT s m)
読み解く
上のコードから、次のことがわかる。
-
StateT s m
は、MonadState
のインスタンスである (m
は Monadインスタンス ) -
StateT
はnewtype
である -
State s
はStateT s Identity
のシノニムである(Identity
は文脈なしのモナド)
∴ State s
は MonadState
のインスタンスとなり、APIのget
、 put
が使える
ここで、StateT
って何?という疑問が激しく生じるが、落ち着いて調べてみると、モナド変換子と呼ばれる類のもののようだ。これについては後日整理する必要があるが、今はそういうものとしておいておく。
終わりに
そういうわけで、StateT
が newtype
であることと、State
は StateT
のシノニムであることがわかった。だから**State
は newtype
である** と言っていいのかは、まだわかっていない。
(2015-04-02 追記) シノニムは別名であり、プログラムを整理しているだけなので、State
は StateT
のシノニムなら、State
は newtype
であると言っても良いだろう、と自己解決。