tick :: State Int Int
tick = get >>= \n ->
       put (n+1) >>= \y ->
       return n

我很困惑,put (n+1)如何对在所有此功能的最终结果没有任何影响。这似乎是这个函数应该返回初始状态不变。我想通过这个在我脑海里跑,但我一直在地方的房间跑出来装东西。 :\

如果有人能走路我通过这个功能的评估,这将是很有益的。

有帮助吗?

解决方案

  

...如何放更新摆在首位的状态?这似乎只是坐在那里什么都不做......

啊,现在我明白你的问题。你想知道如何put(和get)工作,对吧?

也许在JavaScript的例子将有助于(与实际可变状态语言):

var s; // mutable state
function get() { return s; }
function put(x) { s = x; }

function tick() {
    var n = get();
    put(n + 1);
    return n;
}

我希望这说明,虽然n不改变,内部状态仍然会得到更新。如果执行两次tick(),状态将被增加的两倍。

要回到哈斯克尔,这里的State单子的完整定义(相关部分):

newtype State s a = State { runState :: s -> (a, s) }

instance Monad (State s) where
    return a = State $ \s -> (a, s)
    m >>= k  = State $ \s -> let
        (a, r) = runState m s
        in runState (k a) r

get   = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)

现在尝试通过手动内联tick>>=returnget进一步扩大您的put例子。希望这将得到更加清晰状态如何工作的。

其他提示

您是完全正确的。的tick“功能”的“结果”是状态的初始值。

现在当然tick是不是真正的“功能”,但可以读取和写入的状态产生结果之前。结果,计算 在这种情况下,的状态的更新,但你还是返回状态的原始值:

-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state

在这种情况下,因为你永远不会再次检查内部tick的状态,你没有看到改变的状态。然而,如果后tick一些其它计算发生,它可以看到更新的状态。

例如,在做tick两次(第二个将读取更新的状态):

-- 4 is the inital state
ghci> runState (tick >> tick) 4
(5, 6)
-- 5 is the result of the tick computation executed twice,
-- 6 is the updated state

它可以帮助使用写呢do符号

tick :: State Int Int
tick = do
    n <- get    -- get the state
    put (n+1)   -- save an incremented state
    return n    -- return the original state

put (n+1)不影响计算的结果,但它改变该被保持的状态单子内的状态。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top