2016-11-25 79 views
2
runState (modify (+1) >> modify (+1)) 0 

有人可以解釋上述代碼如何產生((),2)嗎?鑑於(>>) :: Monad m => m a -> m b -> m b我會認爲第一個「修改(+1)」將被丟棄,導致((),1)。Haskell(>>)運算符

回答

6

>>運算符不是flip const,即使它具有類似的類型簽名。如果你看一下默認的實現,你可以看到它實際上是在它的第一個參數調用>>=

a >> b = a >>= \_ -> b 

出於這個原因,你能想到的>>運行它的「副作用」一個一元行動,但丟棄結果。如果您直列>>上述定義代替你的榜樣,你得到的結果就變得非常清晰:

runState (modify (+1) >>= \_ -> modify (+1)) 0 

的狀態單子的背景下這顯然運行modify (+1)的兩倍,因此產生的狀態中會2 ,而不是1

3

您可以件事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)