(>>) :: 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.Strict , Control.Monad.State.Strict , State 实际上只是一个类型的同义词:
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 回答
你说得对 .
>>
实际上比你建议的更通用,但你肯定可以使用你指出的类型签名 . 如果您正常使用State
,或其家外之家Control.Monad.State.Strict
,Control.Monad.State.Strict
,State
实际上只是一个类型的同义词:其中
Identity
来自Data.Functor.Identity
并已定义和
StateT
已定义所以
State s a
只是一个新型包装器这与您想象的定义基本相同,但它允许
State s
与monad变换器StateT s
兼容,后者用于向任意Monad
添加状态 .所以
不相关的附注
StateT
的定义让我很恼火,因为在我看来,它把对的元素排列错误 . 为什么错?因为(a, s)
上的映射会改变s
而单独留下a
,这不是映射状态转换器时发生的情况 . 最终结果:直觉不佳 .我认为this Wikipedia page为
State
monad给出(>>=)
的定义:由于
(>>)
是按(>>=)
实施的,如下所示:可以为状态monad导出
(>>)
的定义:或者去除噪音时:
现在因为
x
不在in
子句中起作用,所以你确实可以使用snd
来获取s
,因此可以将其重写为: