然后状态 Monad (>>)

State Monad then (>>)

我想知道 Haskell 状态 monad 的 >> 的定义。

据我猜测,它将一种状态传递到另一种状态:

(>>) :: State s a -> State s b -> State s b
State a >> State b = State $ \x -> b $ snd ( a x )

State a >> State b = State $ b . snd . a

这是正确的吗?

我认为 this Wikipedia pageState monad 给出了 (>>=) 的定义:

m >>= f = \r -> let (x, s) = m r in (f x) s

由于(>>)是根据(>>=)实现的,如下:

m >> k = m >>= \_ -> k

可以推导出状态 monad 的 (>>) 的定义:

m >> k = \r -> let (x, s) = m r in ((\_ -> k) x) s

或去除噪音时:

m >> k = \r -> let (x, s) = m r in k s

既然 x 不参与 in 子句,你确实可以使用 snd 得到 s,因此可以重写为:

m >> k = \r -> k $ snd m r

你说的很对。 >> 实际上比你建议的更通用,但你当然可以将它与你指定的类型签名一起使用。如果您使用的是 State 来自其通常的家,Control.Monad.Trans.State.Strict,或者它的家外之家,Control.Monad.State.StrictState 实际上只是一个类型同义词:

type State s = StateT s Identity

其中 Identity 来自 Data.Functor.Identity 并定义

newtype Identity x = Identity x

StateT定义

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

所以 State s a 只是

的新型包装器
s -> Identity (a, s)

这和你想象的定义本质上是一样的,但是它允许State s兼容monad transformer StateT s,它被用来将状态添加到任意 Monads.

instance Monad m => Monad (StateT s m) where
  return a = StateT $ \s -> return (a, s)
  StateT g >>= f = StateT $ \s -> g s >>= \(r,s') -> runStateT (f r) s'

所以

  StateT g >> StateT h = StateT $ \s -> g s >>= \(_,s') -> h s'

                       = StateT $ \s -> h $ snd $ runIdentity (g s)
                       = StateT $ h . snd . runIdentity . g

不相关的旁注

StateT 的定义让我很烦,因为在我看来它把对的元素放在错误的顺序。为什么错了?因为 (a, s) 上的映射改变了 sa 单独存在,这不是在状态转换器上映射时发生的情况。最终结果:直觉不佳。