我想知道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
这是对的吗?
答案 0 :(得分:4)
你说得对。 >>
实际上比您建议的更为通用,但您当然可以将其与您指明的类型签名一起使用。如果您使用State
来自其通常的家Control.Monad.Trans.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
,而这不是映射状态转换器时发生的情况。最终结果:直觉不佳。
答案 1 :(得分:2)
我认为this Wikipedia page为(>>=)
monad提供了State
的定义:
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
,因此可以将其重写为:{/ p>
m >> k = \r -> k $ snd m r