4

根据State Monad的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))

如上所述,我再次不明白这一点。

所以,如果你能为我解释这个奇怪的结果,那就太好了。;)

提前致谢

此致,

吉米

4

3 回答 3

9

这是因为您在 之后做了一些事情get,即您return是组件之一。忽略新类型包装,

return x = \s -> (x,s)

所以

do { (a,b) <- get; return a }   ===   get >>= \(a,b) -> return a

扩展到

(\s -> (s,s)) >>= \(a,b) -> (\t -> (a,t))

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

\s1 -> let (r,s2) = (\s -> (s,s)) s1
       in (\(a,b) -> (\t -> (a,t))) r s2

当你以初始状态运行它时(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))

其他情况与此return b类似。

于 2012-08-02T22:06:23.657 回答
5

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

您预计((False,0),(False,0))会被退回

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

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

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

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

也许您感到困惑get,并且runState;后者返回一个元组,其中一个组件是计算的结果,另一个是最终状态。事实上,你会把那个元组拆开来只获得(最终)状态。get然而,它有一个返回值,它只是(当前)状态,仅此而已——不需要解元组。如果您确实将元组拆开并仅返回a(或b),那么正如您所观察到的那样,这会相应地显示为完整有状态计算的结果。

于 2012-08-02T23:27:09.980 回答
2

让我们尝试第三个答案:

确实如此get = \s -> (s,s),但是(在 State 的情况下)do-notation 内的箭头只输出value。这都是因为bind这个单子的定义。

所以,你没有得到整对(s,s)。你得到的只是第一个s

您提供了初始状态 = (False,0); <-箭头为您提供复制的值并将其(False,0)绑定到(a,b).

然后围绕 value 构建一个 state monad a = False。这个 monad 将返回(a,s),那就是(False,(False,0)).

初始状态在运行期间没有改变,因为既没有getreturn没有修改它。

于 2014-06-02T07:23:37.827 回答