有人能走我通过这个哈斯克尔功能(州单子相关的)?
题
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
,>>=
,return
和get
进一步扩大您的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)
不影响计算的结果,但它改变该被保持的状态单子内的状态。
不隶属于 StackOverflow