runState (modify (+1) >> modify (+1)) 0
有人可以解释上面代码是如何生成的((),2)吗?给定(>>) :: Monad m => m a -> m b -> m b
我会认为第一个“修改(+1)”将被删除导致((),1)。
答案 0 :(得分:6)
>>
运算符不是flip const
,即使它具有类似的类型签名。如果查看默认实现,可以看到它实际上在第一个参数上调用>>=
:
a >> b = a >>= \_ -> b
出于这个原因,您可以将>>
视为为其“副作用”运行monadic动作,但丢弃结果。如果您将上述>>
的定义内联到您的示例中,您得到的结果就会变得非常明确:
runState (modify (+1) >>= \_ -> modify (+1)) 0
这显然会在状态monad的上下文中运行modify (+1)
两次,因此结果状态为2
,而不是1
。
答案 1 :(得分:3)
你可以将State s
monad视为:
newtype State s a = State { runState :: s -> (a, s) }
让我们看看如何为这个monad实现operator(>>):
(State f) >> (State g) = State (g . snd . f)
如何修改工作:
modify f = State $ \s -> ((), f s)
所以一起撰写:
modify (+1) >> modify (+1) => (State $ \s -> ((), s + 1)) >> ((State $ \s -> ((), s + 1)) => State (\s -> ((), (s + 1) + 1))
然后:
runState (State (\s -> ((), (s + 1) + 1))) 0 => (\s -> ((), (s + 1) + 1)) 0 => ((), (0 + 1) + 1) => ((), 2)