哈斯克尔州莫纳德

时间:2015-10-18 04:19:44

标签: haskell state-monad

确实放了' op在状态Monad(Haskell)中,更新实际状态还是仅返回具有新值的新状态?我的问题是,State Monad能否像一个全球变量一样使用"在一个必要的环境?并且确实放了'修改"全局变量"?

我的理解是NO它不会修改initialState,但是使用monadic接口我们可以绕过新状态b / w计算,保持初始状态"完整"。它是否正确?如果没有,请纠正我。

感谢。

3 个答案:

答案 0 :(得分:5)

{"access_token":"ABCDEFG","expires_in":5183078} 没有什么神奇之处。你可以像这样实现它:

State

也就是说,newtype State s a = State {runState :: s -> (a, s)} (我们认为是使用类型State s a的状态来生成类型s的结果的计算)只是一个函数state并返回结果和新状态。您应尝试为此定义写出a实例以及Monadget的定义。真正的定义更为通用:

put

这允许将状态添加到其他monadic计算中。也可以将状态变换器定义为“操作单元”。 Apfelmus在某个地方有一个教程。

答案 1 :(得分:4)

答案在于类型。

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

因此,状态本质上是一个带有一个参数的函数,&#39> s' (我们称之为状态),并返回一个元组(值,状态)。 monad实现如下

instance Monad (State s) where
  return a = State $ \s -> (a,s)
  (State f) >>= h = State $ \s -> let (a,s') =  f s
                                  in (runState h a) s'

因此,你有一个在初始状态下运行的函数,并吐出一个值状态元组,由组合中的下一个函数处理。

现在,put是以下功能。

put newState = State $ \s -> ((),newState)

这实际上设置了将传递给合成中的下一个函数的状态,而下游函数将看到修改后的状态。

事实上,国家monad是完全纯粹的(也就是说,没有任何东西被设置);只有传递下游的变化。换句话说,状态monad可以省去用Haskell这样的纯语言明确地携带状态的麻烦。换句话说,State monad只是提供了一个隐藏状态线程细节的接口(我认为这是WikiBooks中的所谓,或者我认为你是Haskell)。

以下显示了这一点。你得到了,它将value字段设置为与state字段相同(注意,当我的意思是设置时,我指的是输出,而不是变量)。 put通过传递给它的值获取状态,递增它并使用这个新值设置状态。

-- execState :: State s a -> s -> s
let x =  get >>= \x -> put (x+10)
execState x 10

以上输出20。

现在,让我们执行以下操作。

execState (x >> x) 10

这将输出30.第一个x通过put将状态设置为20。现在,第二个x使用了它。此时get设置状态将其传递给值字段,现在为20.现在,我们的put将获得此值,将其递增10并将其设置为新状态。

因此,您在纯粹的背景下拥有状态。希望这会有所帮助。

答案 2 :(得分:1)

首先,国家不是“全球性”的;你可以有几个不同的状态monad副本运行,每个副本都有自己独立的状态,并且它们不会相互干扰。 (事实上​​,这可以说是重点。)如果你希望状态对整个程序是全局的,那么你必须把整个程序放到一个状态monad中。

其次,调用put会更改后续调用get的结果。就这样。它不会“改变”实际值本身。比如,如果您调用get并将结果放入某个变量,然后调用put,则您的变量不会更改。即使状态是字典或其他东西,如果你要添加一个新密钥和put,那么任何仍在查看字典旧版本的人仍会看到旧字典。这对州monad来说并不特别;这就是Haskell的工作方式。