【问题标题】:How does `get` work in the CPS version of the State monad?`get` 在 State monad 的 CPS 版本中是如何工作的?
【发布时间】:2017-11-17 05:36:39
【问题描述】:

我试图理解这个tutorial之后的一般延续。

但是,我很难理解第 2.10 节中的以下示例:

# let get () =
    shift (fun k -> fun state -> k state state) ;;
get : unit => ’a = <fun>

state 我想是int 类型。我没有得到k 的类型。根据我的理解,k 捕获所有计算随后在get () 之后进行,并且由于我们正在谈论状态单子,k 可以合理地表示将通过采用int 继续进行的计算,因此

k : int => 'a

但从代码来看,它似乎并没有这样做,它需要state 第二次,这实际上意味着:

k : int => int => 'a

但我不知道第二个是从哪里来的,从某种意义上说get 的类型是unit =&gt; 'a 而不是unit =&gt; int =&gt; 'a

与实际的 state monad 实现相比,混乱增加了更多:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

即状态转换表示为从状态到结果和状态元组的函数,这符合我的第一个理解。

谁能给个指导?

其次,我应该如何使用 Haskell 的 Control.Monad.Trans.Cont 在这里实现 get?我在调整类型系统时遇到问题。


更新

看来我得到了第二个:

Prelude Control.Monad.Trans.Cont> let get () = shift $ \k -> return $ \i -> k i i

但我仍然不明白为什么我需要将状态两次应用于延续。

【问题讨论】:

  • @Bergi 它实际上被称为 OchaCaml。我正在学习本教程,但我认为在这种情况下使用的语言不会影响对概念的理解。

标签: haskell ocaml continuations state-monad delimited-continuations


【解决方案1】:

您在state 上应用k 两次,因为第一个对应于get () 的结果(我们希望get 的效果是检索当前状态并将其作为结果返回)和第二个一个对应于将get 之后的状态(因为get 不会改变状态,与get 之前的状态相同)传递给下一个有状态计算。

换句话说,由于状态单子是State s a ~ s -&gt; (a, s),它的CPS版本是State s r a ~ s -&gt; (a -&gt; s -&gt; r) -&gt; r,所以对于get : State s s,因为a ~ s,延续将是一个s -&gt; s -&gt; r类型的函数。

【讨论】:

  • 这是我不明白的主要部分。仅仅通过当前状态就足够了吗?我也不明白如何从 state monad 版本升级到 cps 版本。
  • 我如何仅通过查看代码就知道延续的类型?我应该看哪个部分,洞还是不洞?
  • 想一想如果get 的结果应该是当前状态+ 1(为了示例,将其固定为State Int),您想要传递什么。后续状态仍将与传入状态相同,但结果会有所不同。所以你需要将state + 1 作为结果参数和state 作为新的状态参数传递给继续。
猜你喜欢
  • 1970-01-01
  • 2012-06-30
  • 2018-12-12
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
相关资源
最近更新 更多