使用 MonadRef 实现 MonadCont

2024-04-08

有一个众所周知的问题我们不能使用forall类型在Cont返回类型 https://stackoverflow.com/questions/7178919/how-to-make-callcc-more-dynamic/7180154#7180154.

不过,有以下定义应该没问题:

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

然后找到一个有意义的例子。在这张纸 http://www.carlssonia.org/ogi/mdo-callcc.pdf作者声称我们可以实施MonadFix在之上ContT r m提供了m实施的MonadFix and MonadRef。但我认为如果我们确实有一个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 = ...

(不幸的是我不熟悉语义shift and reset所以我没有为他们提供实现)

这个实现对我来说似乎没问题。直观地讲,当callCC'被召唤,我们喂养k其自身效果总是失败的函数(尽管我们无法提供任意类型的值b,但我们总能提供mzero类型的m b并且根据法律,它应该有效地停止计算所有进一步的影响),并且它捕获接收到的值作为最终结果callCC'.

所以我的问题是:

此实现是否按理想的预期工作callCC?我们可以实施吗shift and reset也有正确的语义吗?

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

为了确保正确的行为,我们必须假设以下属性MonadRef。那么法律会怎样规定MonadRef为了使上述实现按预期运行?

UPDATE

事实证明,上述简单的实现还不够好。使其满足“持续电流”

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还不够,我们必须能够结合mzero值与正常计算而不取消整个计算。

以上并没有回答问题,只是由于最初的尝试被伪造为候选人而进行了调整。但对于更新后的版本来说,原来的问题仍然是问题。尤其,reset and shift仍有待实施。


(这还不是答案,但我脑海中只出现了一些线索。我希望这将导致我自己或其他人真正的答案。)

按值调用与按名称调用是双重的 http://homepages.inf.ed.ac.uk/wadler/papers/dual/dual.pdf——菲利普·瓦德勒

在上面的论文中,作者介绍了“对偶演算”,一种与经典逻辑相对应的类型演算。在最后一节中,有一段说

按需呼叫的双重策略可以 通过用余值覆盖余项来避免这种低效率 第一次评价。

正如 Wadler 的论文中所述,按名称调用急切地评估延续(它在评估所有值之前返回),而按值调用延迟评估延续(它仅在评估所有值之后返回)。

现在,看一下callCC'上面,我相信这是延续侧按需调用的双重示例。评估的策略是为给定的函数提供一个假的“延续”,但缓存此时的状态以便稍后调用“真实”的延续。这在某种程度上类似于对延续进行缓存,因此一旦计算完成,我们就恢复该延续。但缓存评估值就是按需调用的意思。

一般来说,我怀疑状态(截至当前时间点的计算)与延续(未来的计算)是对偶的。这将解释一些现象。如果这是真的,那就不足为奇了MonadRef(对应于全局和多态状态)是对偶的MoncadCont(对应于全局和多态延续),因此它们可以用来相互实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 MonadRef 实现 MonadCont 的相关文章

随机推荐

  • 如何更改 Visual Code Studio 提交作者

    我不知道为什么 但我的 Visual Studio Code 显示错误的提交作者姓名 我正在尝试更改提交的作者 我怎样才能做到这一点 我已经有很多东西了 但没有运气 这是我尝试过的 由于我有三个提交 所以我尝试了git rebase i H
  • 如何排除“git diff-index”中的文件

    我正在使用 git 预提交挂钩来检查提交 预提交脚本基本上做了一件事 exec git diff index check cached HEAD 它还做了一些其他事情 但它们与本次讨论无关 问题是 我的存储库中有各种各样的文件 但并非所有文
  • 通过单击按钮旋转/翻转两种布局

    我有两个布局 xml 文件 我想从一个页面翻转到另一个页面 这两个 xml 文件是 main xml 和 register xml 如果我单击 main xml 中的登录按钮 页面应该翻转并显示 register xml并且在 regist
  • 在 Anaconda 中安装 Kivy

    我正在尝试在 Windows 7 的 Anaconda 3 4 1 1 中安装 Kivy 但我找不到合适的用户指南来指导我如何安装 但到目前为止 我能够在链接上找到在 OS X 上安装它的说明https github com kivy ki
  • matplotlib 中的曲面图

    我有一个 3 元组列表 表示 3D 空间中的一组点 我想绘制一个覆盖所有这些点的曲面 The plot surface函数在mplot3d包要求参数 X Y 和 Z 为二维数组 是plot surface绘制曲面的正确函数以及如何将数据转换
  • 使用 Ruby Date 类处理天文数据

    大约太阳正午 lw 88 743 my longitude jdate Date ordinal to jd Time now year Time now yday n jdate 2451545 0 0009 lw 360 round l
  • 如何在x86汇编编程中表示诸如FFFFFFBB之类的十六进制值?

    我正在学习 x86 内联汇编编程 我想写mov ecx FFFFFFBB 但是编译器无法识别它 像这样的十六进制数字应该如何在内联汇编代码中编写 这取决于您的汇编器的风格 美国电话电报公司 movl 0xFFFFFFBB ecx Intel
  • PyCharm:FooTestCase 不是测试,但 FooTest 是

    如果我打电话给我的测试班FooTestCase我没有看到绿色播放按钮来运行测试 如果我删除 Case 并调用它FooTest出现绿色播放按钮 为什么会发生这种情况 我想要有播放按钮来运行 FooTestCase 的测试 None
  • ANDROID SQLITE 检查表是否有数据

    我想检查一下我的表是否有记录 这是我尝试过的 if cursor null cursor moveToFirst if cursor getInt 0 0 Toast makeText getBaseContext No records y
  • 为什么编译器会生成这个程序集?

    在逐步执行一些 Qt 代码时 我遇到了以下情况 功能QMainWindowLayout invalidate 有以下实现 void QMainWindowLayout invalidate QLayout invalidate minSiz
  • Kendo UI 数据源 - 过滤相关数据

    我在过滤相关数据 多对多 的剑道数据源时遇到问题 我正在使用 ASP NET WebAPI2 和 DataSourceRequest 来捕获服务器上的请求 然后使用 IQueryable 上的 ToDataSourceResult 扩展方法
  • Laravel 4 调用未定义的方法 Illuminate\Database\Eloquent\Collection::links()

    我尝试实现书中的代码 学习 Laravel 4 应用程序开发 http www packtpub com learning laravel 4 application development book 一个简单的使用 CRUD 应用程序如下
  • boost::process::child 关闭输入流后不会退出

    在下面的示例中 我尝试将一些数据写入子进程 该子进程处理数据并将其写入文件 关闭流后 父进程无限期地等待子进程完成 我不知道如何表明我已完成写入数据 并希望子进程停止读取并完成它正在做的任何事情 根据文档调用终止会发送一个SIGKILL h
  • 如果没有 iPad,如何在 iPad 上测试我的网站?

    我收到评论说我的一位网站 tumblr 主题 http www tumblr com theme 11037在 iPad 上崩溃 我没有 iPad 所以我想知道您将如何在 iPad iPhone 或任何其他智能手机上测试您的网站 如果您使用
  • JQuery:帮助使用 .each() 和 .append() 将图片添加到 HTML

    需要修复的简单错误 我不知道出了什么问题 我需要将同一张图片附加到 HTML 中的多个 五个 div 由于某种原因 我的代码将同一张图片附加到每个 div 五次 更清楚地说 五个 div 中的每一个都需要一张图片 现在 这五个人每人都有五张
  • 在另一台计算机上运行 C# 程序时出现 System.IO.FileLoadException

    我目前正在开发一个 C WPF 项目 该项目使用 MySQL Data 和 System Data Sqlite dll 以及其他几个 该项目是一个 Net 4 项目 在我的开发机器上运行没有问题 我创建了一个 MSI 安装程序包 当我添加
  • 对 geom_tile 内的数据进行排序

    我有一个数据框 我想生成一个geom tile 从中绘制 但我希望图表的排序不是基于字母顺序 而是基于该数据框中的变量 structure list V1 c a y w p v h i V2 c r w q m l q g V3 c 5
  • Visual Studio 2010 Express 是否会阻止源代码管理插件?

    我尝试在我的 Visual Studio 2010 Express 上安装此插件 http gitscc codeplex com http gitscc codeplex com 但我在插件存储库中找不到它 插件的 源代码管理 类别是空的
  • 从 PageAsyncTask 调用的方法中,HttpContext.Current 为 null

    我有一个场景 我有一个页面 单击按钮即可打开一个对话框 在单击按钮打开的对话框表单中 我可以从选定的 txt 文件中读取数据列表并构建查询并将数据添加到某些数据库表 由于可能存在大量数据 此过程可能需要很长时间 因此用户在上传完成之前将无法
  • 使用 MonadRef 实现 MonadCont

    有一个众所周知的问题我们不能使用forall类型在Cont返回类型 https stackoverflow com questions 7178919 how to make callcc more dynamic 7180154 7180