使用MonadRef实现MonadCont

时间:2014-06-16 06:20:46

标签: haskell continuations delimited-continuations

有一个众所周知的问题we cannot use forall types in the Cont return type

但是,可以使用以下定义:

class Monad m => MonadCont' m where
    callCC' :: ((a -> forall b. m b) -> m a) -> m a
    shift :: (forall r.(a -> m r) -> m r) -> m a
    reset :: m a -> m a

然后找到一个有意义的实例。在this paper中,作者声称我们可以在MonadFix之上实施ContT r m,前提是m已实施MonadFixMonadRef。但我认为,如果我们确实有MonadRef,我们实际上可以实现callCC',如下所示:

--satisfy law: mzero >>= f === mzero
class Monad m => MonadZero m where
    mzero :: m a

instance (MonadZero m, MonadRef r m) => MonadCont' m where
    callCC' k = do
        ref <- newRef Nothing
        v <- k (\a -> writeRef ref (Just a) >> mzero)
        r <- readRef ref
        return $ maybe v id r
    shift = ...
    reset = ...

(不幸的是,我不熟悉shiftreset的语义,所以我没有为它们提供实现)

这个实现对我来说似乎没问题。直观地,当callCC'被调用时,我们向k提供其自身效果始终失败的函数(尽管我们无法提供任意类型b的值,但我们可以始终提供类型为mzero的{​​{1}},并且根据法律,它应该有效地停止计算所有进一步的效果),并将接收到的值作为m b的最终结果。

所以我的问题是:

此实施是否符合理想callCC'的预期效果?我们是否可以使用适当的语义实现callCCshift

除了上述内容,我想知道:

为了确保正确的行为,我们必须假设reset的某些属性。那么为了使上述实现具有预期的行为,MonadRef所具有的法律是什么?

更新

事实证明,上述天真的实现还不够好。使其满足&#34;延续当前&#34;

MonadRef

我们必须将实施调整为

callCC $\k -> k m === callCC $ const m === m

换句话说,原始instance (MonadPlus m, MonadRef r m) => MonadCont' m where callCC' k = do ref <- newRef mzero mplus (k $ \a -> writeRef ref (return a) >> mzero) (join (readRef ref)) 是不够的,我们必须能够使用正常计算将MonadZero值组合而不取消整个计算。

以上内容没有回答这个问题,只是因为最初的尝试被伪造为候选人而进行了调整。但对于更新版本,原始问题仍然是问题。特别是,mzeroreset仍有待实施。

1 个答案:

答案 0 :(得分:2)

(这还不是一个答案,但只有一些线索出现在我的脑海里。我希望这会通过我自己或其他人得到真正的答案。)

  

Call-by-Value is Dual to Call-by-Name - Philip Wadler

在上面的论文中,作者介绍了&#34; Dual Calculus&#34;,这是一种与经典逻辑相对应的类型演算。在上一节中,有一段称为

  

双重呼吁的策略可以   通过用其covalue覆盖coterm来避免这种低效率   第一次评估。

正如Wadler的论文中所述,逐个名称地逐个评估连续性(它在所有被评估的值之前返回),同时按值调用延迟评估连续性(它仅在所有值被评估之后返回) )。

现在,看一下上面的callCC',我相信这是继续方面的双重需求的双重例子。评估的策略是提供假的继续&#34;到给定的函数,但在此时缓存状态以调用&#34; true&#34;继续以后。这就像制作延续的缓存一样,所以一旦计算完成,我们就恢复那个延续。但缓存评估值是指按需调用的含义。

一般来说,我怀疑,状态(计算到当前时间点)是连续的两倍(未来的计算)。这将解释一些现象。如果这是真的,那么MonadRef(对应于全局和多态状态)对MoncadCont是双重的(对应于全局和多态连续)并不奇怪,因此它们可用于实现彼此。