首页 文章

State Monad然后(>>)

提问于
浏览
1

我想知道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

它是否正确?

2 回答

  • 4

    你说得对 . >> 实际上比你建议的更通用,但你肯定可以使用你指出的类型签名 . 如果您正常使用 State ,或其家外之家 Control.Monad.State.StrictControl.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变换器 StateT s 兼容,后者用于向任意 Monad 添加状态 .

    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) 上的映射会改变 s 而单独留下 a ,这不是映射状态转换器时发生的情况 . 最终结果:直觉不佳 .

  • 2

    我认为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
    

相关问题