关系建模与 APL
摘要
作者探讨了利用约束逻辑和等式重写规则,将关系建模与 APL 风格的数组语言相结合,并讨论了如何将属性定义为双向推导,而非简单的赋值。
<p><a href="https://lobste.rs/s/deceli/relational_modeling_apl">评论</a></p>
查看缓存全文
缓存时间: 2026/05/10 06:48
# 关系建模与 APL ⁑ Dercuano
来源:https://dercuano.github.io/notes/relational-modeling-and-apl.html
Kragen Javier Sitaker,2019-05-20(更新于 2019-05-21)(5 分钟)
我认为存在一种逻辑编程或约束逻辑的方法,它保留了数组语言的大部分优点,同时增加了像 Prolog 以及尤其是 miniKANREN 那样的多向推理能力。
我注意到这些笔记在我反复写下相同想法(却又把它们忘掉)时变得越来越重复;我会尝试在这里链接它们。
今天或昨天,我在思考面向对象的条件重写规则(http://lists.canonical.org/pipermail/kragen-tol/2007-March/000855.html)以及带有面向对象条件重写规则的 IRC 机器人(https://dercuano.github.io/notes/funbot.html),想着如果能这样定义属性会很棒:“`.vol = π.r²·.h; .area = 2π.r(.h + .r)`”,这样当访问 `foo.area` 时,系统会搜索可应用的公式,如果碰巧 `foo` 拥有 `.h` 和 `.r` 属性,就使用那个公式。(我脑海中模糊地挥手示意,某种命名空间机制可以将其别名化为 `foo.cylinder::h`,从而避免与例如 `foo.planck::h` 发生冲突。)这使我意识到,这与《对 APL 等数组语言的有原则的重新思考》(https://dercuano.github.io/notes/principled-apl.html)中关于数组兼容性的思考完全一致。(并且在《OMeta 包含 Wadler 的“视图”》(https://dercuano.github.io/notes/views-and-ometa.html)中,我指出它们与 Wadler 的视图是同一回事。)
不过,两者的区别在于,在重写规则的思维方式中,单个属性可以有多个定义,就像在不同 OO 类中被重写的方法一样,通常只有一种是可应用的;而在《对 APL 等数组语言的有原则的重新思考》(https://dercuano.github.io/notes/principled-apl.html)中,除了显式条件语句外,并未考虑此类合并。
在《带有面向对象条件重写规则的 IRC 机器人》(https://dercuano.github.io/notes/funbot.html)中,我曾建议通过特异性排序来解决冲突,就像 CSS 或 Aardappel 那样。但将重写规则视为*推理规则*则暗示了另一种替代方案。假设我们将 `.vol = π.r²·.h` 读作通常意义上的方程规范——即在变量已定义的所有情况下已知成立的关系。在这种情况下,它定义了一个*约束*,这意味着我们不仅可以利用它来计算 `.vol`,如果我们恰好从其他地方知道了 `.vol` 和 `.r`,还可以利用它来计算 `.h`。这意味着它也是一种*断言*——如果我们从其他定义中对 `.vol` 有不同的计算结果,这两个值必须一致,否则我们就发现了模型中的不一致性!
所以,这是处理“重写规则”冲突的另一种方式——如果两个冲突的定义给出不同的结果,则让程序崩溃。
(当然,Prolog 将冲突的定义视为同样有效的可能性,尽管它们有明确的顺序;只有当我们从第一个定义回溯时,才会使用第二个定义。)
但我们无需放弃《对 APL 等数组语言的有原则的重新思考》(https://dercuano.github.io/notes/principled-apl.html)(以及《带有类型索引的 APL》(https://dercuano.github.io/notes/typed-apl.html)和《索引族编程的索引集推断或域推断》(https://dercuano.github.io/notes/matrix-multiply.html))中隐式循环带来的美妙体验,就能实现这一点,只需声明类似 `.r = [1mm 2mm 5mm 10mm]` 的内容,这意味着存在由不同半径定义的四种感兴趣的情况。这些“不同的圆柱体”都可以“继承”一个共同的 `.h`,拥有一个随 `.r` 变化的 `.h`,或者拥有一个独立于 `.r` 变化的 `.h`。其底层逻辑是对各种不同情况的条件推理。
我曾在《关于强大原语的思考》(https://dercuano.github.io/notes/powerful-primitives.html#addtoc_12)中简要讨论过这种联系。
两年前,我在《关系建模》(https://dercuano.github.io/notes/relational-modeling.html)中几乎原封不动地写下了这些想法。
通过使用 miniKANREN 提供的功能更强大的关系编程,而不是 Prolog 使用的较有限的类型,我们可能能够求解更多的模型。此外,对于像我上面用作示例的数值关系,区间算术或仿射算术可能非常有用,原因有二——首先,为了使系统取得进展,或者证明系统无解,当系统开始时约束不足时(考虑 `.x = exp(.x)`,它没有解,或 `.x = exp(.x)/4`,它有两个解),其次,用于确定通过不同计算路径到达的数值的两个值是否确实相等。(区间算术不能证明值相等,但它能可靠地判断表观差异是否大到不可能由舍入误差引起。)
这里存在潜在的冲突,即使用已知值的隐式模式来区分属性*不存在*的情况(例如试图寻找立方体的半径)和属性*尚未知道*的情况。我怀疑,为了解决这一冲突,可能存在不同的有效设计选择,这些选择会导致有趣的不同语言,适用于不同的目的。
## 主题
- 编程(https://dercuano.github.io/topics/programming.html)(286 条笔记)
- 编程语言(https://dercuano.github.io/topics/programming-languages.html)(47 条笔记)
- 区间和仿射算术(https://dercuano.github.io/topics/intervals.html)(24 条笔记)
- 数组(https://dercuano.github.io/topics/arrays.html)(17 条笔记)
- 约束满足(https://dercuano.github.io/topics/constraints.html)(9 条笔记)
- APL(https://dercuano.github.io/topics/apl.html)(9 条笔记)
- Prolog 和逻辑编程(https://dercuano.github.io/topics/prolog.html)(8 条笔记)
- 谓词逻辑(https://dercuano.github.io/topics/predicate-logic.html)(6 条笔记)
- miniKANREN(https://dercuano.github.io/topics/minikanren.html)(6 条笔记)
相似文章
对 APL 等数组语言的有原则性重新思考
本文提出了一种有原则性的方法来重新思考 APL 等数组语言,通过将变量建模为输入维度的函数,旨在相较于传统方法提高可读性和错误检查能力。
语言模型中基于单元的关系绑定表示
研究表明,大型语言模型通过“基于单元的绑定表示”(CBR)对篇章级关系绑定进行编码:一种低维线性子空间,每个“单元”对应实体-关系索引对,为模型如何追踪实体与关系提供了因果证据。
无点逻辑编程
本文探讨了无点逻辑编程,这是一个与函数式编程范式相关的概念。
逻辑程序的抽象机
本文探讨了使用抽象栈机器实现逻辑程序的方法,详细说明了推理规则(如加法)的不同模式分配如何转换为状态机转换以进行计算。
追踪大语言模型中的关系知识回忆
研究者通过探测每个注意力头的贡献,追踪大语言模型如何回忆关系事实,发现这些贡献是强线性特征,其保真度与关系特异性及实体连接度相关。