Control.MonadPlus.Free,无需不必要的分发

2024-03-04

我正在尝试使用免费的 monad 构建 EDSL,用于构建像 Prolog 这样的 AND/OR 决策树,其中>>=映射到 AND,并且mplus映射到 OR。我希望能够描述类似的东西A AND (B OR C) AND (D OR E),但我不希望分配性将其变成(A AND B AND D) OR (A AND B AND E) OR (A AND C AND D) OR (A AND C AND E)。最终,我想将 AND/OR 节点转换为约束求解器中的具体化约束,而不会导致我希望求解器处理的替代方案数量出现组合爆炸。

In Control.MonadPlus.Free, Plus ms >>= f causes f应用于每个Pure每个单子下的叶子ms。这是必要的,因为f每个可能会产生不同的值Pure它所取代的叶子。

然而,在Plus ms >> g, g不会受到任何叶子的影响ms,因此将其分布在Plus似乎没有必要。

通过反复试验,我发现我可以扩展Control.MonadPlus.Free带有新的单子Then构造函数:

data Free f a = Pure a
              | Free (f (Free f a))
              | Then [Free f ()] (Free f a)
              | Plus [Free f a]

在这里,新Then构造函数包含一系列我们忽略其值的 monad,后面是产生实际值的最终 monad。新的Monad实例看起来像:

instance Functor f => Monad (Free f) where
    return = Pure

    Pure a >>= f = f a
    Free fa >>= f = Free $ fmap (>>= f) fa
    Then ms m >>= f = Then ms $ m >>= f
    Plus ms >>= f = Plus $ map (>>= f) ms

    Pure a >> mb = mb
    Then ms ma >> mb = Then (ms ++ [ma >>= (const $ return ())]) mb
    ma >> mb = Then [] ma >> mb

The >>运算符通过替换来“限制”任何现有的叶子Pure a with Pure (),将 capped monad 添加到列表中,并用新值替换值 monad。我意识到附加新单子的效率低下++,但我认为这和>>=将新的 monad 缝合到链的末端fmap(并且整个事情可以使用延续来重写)。

这看起来合理吗?这是否违反了单子定律(这很重要吗?),或者是否有更好的方法来使用现有的Control.Monad.Free?


你可能想看看我的操作 http://www.haskell.org/haskellwiki/Operational包,这是对免费 monad 的不同看法。

特别是,看看广度优先解析.hs https://github.com/HeinrichApfelmus/operational/tree/master/doc/examples#example-code-for-the-operational-package例子。它具有一个mplus操作使得>>= does not自动分配到它上面。这允许您以广度优先的方式实现解析器组合器。

翻译为Control.Monad.Free,重点是如果你使用函子

data F b = MZero | MPlus b b

then Free F会自动分配>>= over mplus。你必须使用函子

data F b = MZero | forall a. MPlus (Free f a) (Free f a) (a -> b)

相反,如果您想实现语义MPlus不会自动分发>>=。 (这就是为什么我更喜欢我的操作库而不是免费库的主要原因。)

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

Control.MonadPlus.Free,无需不必要的分发 的相关文章

随机推荐

  • Xpath 表达式

    我需要获得的价值
  • 无法访问复制到 /var/www/ 或其他文件夹中的 php 文件

    我使用的是带有 LAMP 设置的 Ubuntu 12 10 我将 Windows PC 上的 xampp htdocs 中包含项目文件 php html css 的子目录复制到我的 ubuntu 的 var www 中 但是 当我从浏览器访
  • reinterpret_cast 与 c 风格强制转换 [重复]

    这个问题在这里已经有答案了 可能的重复 c 风格强制转换与reinterpret cast https stackoverflow com questions 8427107 c style cast vs reinterpret cast
  • Tridion 命令扩展如何找到它扩展的命令?

    Tridion 的用户界面允许您扩展特定的命令 这是修改某些现有命令的行为的好方法 在编辑器的配置文件中 这是通过如下部分完成的
  • 通过反射获取枚举值

    我试图在运行时循环并打印给定枚举类的所有枚举值 但我似乎只能返回与值相关的常量 大多数解决方案都指向使用 getEnumConstants values 或 valueOf 但我无法让它们按预期工作 我能找到的最接近的问题是通过反射获取en
  • Android VOIP SipException:无法创建 SipSession

    我正在尝试使用 Android 3 1 上内置的 SIP 运行 VOIP 呼叫 我有物理平板电脑设备 galaxy Tab 10 1 为了测试目的 我创建了一个项目SipDemo 示例 http developer android com
  • NotYetImplemented 错误 ng2-charts

    从 utils js 收到消息 NotYetImplemented 的错误 我在使用nodejs服务器时收到错误 这个错误到底意味着什么 当我使用 ngserve 时 没有这样的错误 我正在使用 ng2 charts 模块中的折线图 完整的
  • 如何检索从 SQL Server 到 VB.NET 受影响的行数?

    基本上 我通过运行时检索程序中的所有数据 我想知道如何检索更新后受影响的行数 以便我可以通过 VB NET 提示用户相关信息 我实际上正在做的是 更新后 如果没有其他行更新 则用户无法再单击按钮 通过使用执行非查询 http msdn mi
  • 子项在父视图之外不可点击

    我创建了一个带有标记的地图视图 看下面这张图 Grandparent是一个填充视图 Parent是我的MarkerView Child是一个可点击的标记 父级有clipChildren false 因此子级是可见的 我的问题是孩子们是可点击
  • 如何在 ASP.NET MVC 区域中的 Web 窗体中使用母版页

    我已将 MVC 区域添加到现有的 Web 窗体项目中 我想在 MVC 项目的所有视图中使用母版页 我不明白我应该如何引用 MVC 区域内的 WebForms 的 MasterPage 我读过这两篇文章 http www hanselman
  • Mercurial 变基场景

    我读过变基项目 http mercurial selenic com wiki RebaseProject页面并尝试了一个不平凡的例子 不是对一个完整的分支进行变基 和这个案例很相似重新建立 D 基础 我场景 B 的情况 这是 rebase
  • Android:如何在onStop之后返回具有“noHistory”属性的Activity?

    我正在寻找一种从历史堆栈中删除某个活动的方法 并找到了解决方案这里 瓦卡斯的回答 https stackoverflow com questions 1898886 removing an activity from the history
  • 续集上的belongsToMany会自动创建新的连接表吗?

    我对这个续集很陌生 我尝试使用belongsToMany通过UserPermissions在用户和权限之间关联模型 这是我的代码 用户 js const bcrypt require bcrypt const config require
  • 如何使用 JavaScript 正则表达式从推文中提取 URL?

    假设我将推文作为字符串存储在 JS 变量中 如何使用 JavaScript 正则表达式从推文中提取 URL 这应该比从字符串中提取 URL 容易得多 因为 我假设任何以 http 或 www 开头并以空格 或推文结尾 结尾的内容都是 URL
  • ios - UIImageView 上的 SizeToFit 不起作用

    我有一个 UIImageView 它从 ios 文件系统上的文档目录加载图像 问题是当我打电话时 imageView sizeToFit 这是行不通的 我认为这是因为图像此时尚未完全加载 因此在获得图像宽度和高度之前调用了 sizeToFi
  • python非阻塞非messing-my-tty按键检测

    我有一个循环可以完成一些工作并将大量信息打印到标准输出 一遍又一遍 这是一个循环 我想做的是检测用户何时 是否按下某个键 可以是箭头 回车键或字母 并在发生这种情况时执行一些工作 这应该是一个非常简单的子任务 但我花了四个小时尝试不同的方法
  • django 更新时的模型验证

    我创建了一个名为 Term 的模型及其验证器 如下所示 from django db import models from django contrib auth models import User from django core ex
  • Rails 3 替换验证

    我是 Rails 新手 但正在阅读有关验证控制器中的参数的文档 它们似乎引用了 verify 方法 但在 Rails 3 中 它显示 verify 已被弃用 这样做的新方法是什么 我收到的错误是 验证已从 Rails 中删除 现在可以作为插
  • 在 Eclipse-Photran 中为 Windows 上的 fortran 编译器配置 LAPACK

    Update 感谢弗拉基米尔对图书馆的有用见解 我采取了另一种方法 首先在 ubuntu 中开发 这比使用 Eclipse Cygwin 容易得多 现在我尝试移植到 Windows 这相当不错 但是我对此也有一些疑问 发布在这里 将 for
  • Control.MonadPlus.Free,无需不必要的分发

    我正在尝试使用免费的 monad 构建 EDSL 用于构建像 Prolog 这样的 AND OR 决策树 其中 gt gt 映射到 AND 并且mplus映射到 OR 我希望能够描述类似的东西A AND B OR C AND D OR E