haskell - 状态monad函数得到?

jim*_*myt 4 monads haskell state-monad

根据State Monad的get函数提出的一个问题:

如果我跑

runState get 1

我得到了结果

(1,1)

这对我来说没问题,因为get函数将结果值设置为状态,在这种情况下状态为1.因此,(1,1)是结果.好.

但是,如果我跑

runState(do {(a,b)< - get; return a})(False,0)

我得到了结果

(假,(假,0))

这个我不明白.

get函数将结果值设置为状态并保持状态不变.所以我期待的是这样的事情

((假,0),(假,0))

与此相同

runState(do {(a,b)< - get; return b})(False,0)

结果是

(0,(假,0))

如上所述,我不再理解这一点.

所以,如果你能解释我这个奇怪的结果,那将是非常好的.;)

提前致谢

最好的祝福,

吉米

Dan*_*her 8

这是因为你在之后做了一些事情get,即你的return一个组成部分.忽略newtype-wrapping,

return x = \s -> (x,s)
Run Code Online (Sandbox Code Playgroud)

所以

do { (a,b) <- get; return a }   ===   get >>= \(a,b) -> return a
Run Code Online (Sandbox Code Playgroud)

扩展到

(\s -> (s,s)) >>= \(a,b) -> (\t -> (a,t))
Run Code Online (Sandbox Code Playgroud)

并且随着它的定义(>>=)变得

\s1 -> let (r,s2) = (\s -> (s,s)) s1
       in (\(a,b) -> (\t -> (a,t))) r s2
Run Code Online (Sandbox Code Playgroud)

当你以初始状态运行时(False,0),它会展开

let (r,s2) = (\s -> (s,s)) (False,0)
~> let (r,s2) = ((False,0),(False,0))
in (\(a,b) -> (\t -> (a,t))) r s2
~> in (\(a,b) -> (\t -> (a,t))) (False,0) (False,0)
~> in (\t -> (False,t)) (False,0)    -- match (a,b) with (False,0)
~> in (False, (False,0))
Run Code Online (Sandbox Code Playgroud)

另一种情况return b类似.


Joa*_*ner 5

丹尼尔的回答当然是正确和完整的,所以让我试着从不同的角度回答它并讨论可能的误解.

你期望((False,0),(False,0))被退回

runState (do{(a,b) <- get; return a}) (False, 0)
Run Code Online (Sandbox Code Playgroud)

现在要实际得到这个预期的结果,你必须写,例如,

runState (do{(a,b) <- get; return (a,b)}) (False, 0)
Run Code Online (Sandbox Code Playgroud)

(这在道德上等同于runState get (False, 0).

也许你是混乱getrunState; 后者返回一个元组,其中一个组件是计算的结果,另一个组件是最终状态.事实上,你将这个元组分开来只获得(最终)状态.get但是有一个返回值,它只是(当前)状态,仅此而已 - 无需解开.如果确实将元组拆开并仅返回a(或b),那么这将作为完整有状态计算的结果显示出来,就像您观察到的那样.