我在弄清楚绑定运算符如何将以下状态单子绑定在一起方面遇到了一些麻烦:
pop :: State [Int] Int
pop = do
(x:xs) <- get
put xs
return x
push :: Int -> State [Int] ()
push x = do
xs <- get
put (x:xs)
doStuff :: State [Int] ()
doStuff = do
pop
x <- pop
push 5
push x
接下来考虑函数doStuff
,可以被转换为以下形式:
pop >>= (\_ -> pop >>= (\x -> push 5 >>= (\_ -> push x)))
当评估这行代码时,绑定实际上是按什么顺序发生的?由于要进行实际的绑定,Haskell需要从右侧函数中获取一个State monad(即需要先完全评估函数右操作数),因此我认为以下情况将发生:
- s1 =
push 5 >>= (\_ -> push x)
- s2 =
pop >>= (\x -> s1)
- s3 =
pop >>= (\_ -> s2)
do
符号给人一种处理一系列操作的假象,而事实上,有许多嵌套和闭包。我感到自己在过度思考并因此进一步混淆自己。
>>=
的定义从状态单子扩展到感受一下会发生什么。没有什么特别的事情,只是普通的求值。 - augustss