runState (modify (+1) >> modify (+1)) 0
有人可以解釋上述代碼如何產生((),2)嗎?鑑於(>>) :: Monad m => m a -> m b -> m b
我會認爲第一個「修改(+1)」將被丟棄,導致((),1)。Haskell(>>)運算符
runState (modify (+1) >> modify (+1)) 0
有人可以解釋上述代碼如何產生((),2)嗎?鑑於(>>) :: Monad m => m a -> m b -> m b
我會認爲第一個「修改(+1)」將被丟棄,導致((),1)。Haskell(>>)運算符
>>
運算符不是flip const
,即使它具有類似的類型簽名。如果你看一下默認的實現,你可以看到它實際上是在它的第一個參數調用>>=
:
a >> b = a >>= \_ -> b
出於這個原因,你能想到的>>
爲運行它的「副作用」一個一元行動,但丟棄結果。如果您直列>>
上述定義代替你的榜樣,你得到的結果就變得非常清晰:
runState (modify (+1) >>= \_ -> modify (+1)) 0
的狀態單子的背景下這顯然運行modify (+1)
的兩倍,因此產生的狀態中會2
,而不是1
。
您可以件事State s
單子如下:
newtype State s a = State { runState :: s -> (a, s) }
,讓我們看看如何操作符(>>)爲這個單子來實現:
(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)