【问题标题】:How does term-rewriting based evaluation work?基于术语重写的评估如何工作?
【发布时间】:2014-06-20 15:35:21
【问题描述】:

纯编程语言是apparently based on term rewriting,而不是传统上作为外观相似语言基础的 lambda 演算。

...这有什么定性和实际的区别?事实上,它评估表达式的方式有什么不同?

链接页面提供了很多术语重写的示例有用,但它实际上并没有描述它与函数应用程序的不同之处,只是它具有相当灵活的模式匹配(和出现在 Haskell 和 ML 中的模式匹配很好,但不是评估策略的基础)。值与定义的左侧匹配并替换到右侧 - 这不只是 beta 减少吗?

模式的匹配和替换为输出表达式,在我看来有点像syntax-rules(甚至是不起眼的#define),但主要特点显然是它发生在之前 而不是在评估期间,而 Pure 是完全动态的,并且在其评估系统中没有明显的相分离(事实上,Lisp 宏系统总是对它们的运行方式发出很大的噪音不与功能应用不同)。能够操作符号表达式值很酷,但也似乎是动态类型系统的产物,而不是评估策略的核心(很确定您可以在 Scheme 中重载运算符以处理符号值;事实上you can even do it in C++ 带有表达式模板)。

那么当替换发生在两者中时,术语重写(Pure 使用的)和传统函数应用程序(作为评估的基础模型)之间的机械/操作差异是什么?

【问题讨论】:

  • @GuyCoder 除其他外,强调问题的工程方面(“它实际上在做什么?”),因为我不是——现在仍然不是——有信心理解科学(“这是什么意思?”)观点。
  • Lambda 只是术语重写的一种特定形式 eval [(λx -> '(+ 1 x)) 5] = replace x by 5 in '(+ 1 x) ,为什么不概括它实现效果系统、线性类型和出色的模式匹配。

标签: functional-programming evaluation rewriting


【解决方案1】:

术语重写不必看起来像函数应用程序,但像 Pure 这样的语言强调这种风格,因为 a) beta-reduction 很容易定义为重写规则,b) 函数式编程是一种易于理解的范例。

一个反例是黑板或元组空间范式,术语重写也非常适合。

beta-reduction 和全词重写之间的一个实际区别是重写规则可以对表达式的定义进行操作,而不仅仅是它的值。这包括对可约表达式的模式匹配:

-- Functional style
map f nil = nil
map f (cons x xs) = cons (f x) (map f xs)

-- Compose f and g before mapping, to prevent traversing xs twice
result = map (compose f g) xs

-- Term-rewriting style: spot double-maps before they're reduced
map f (map g xs) = map (compose f g) xs
map f nil = nil
map f (cons x xs) = cons (f x) (map f xs)

-- All double maps are now automatically fused
result = map f (map g xs)

请注意,我们可以使用 LISP 宏(或 C++ 模板)来做到这一点,因为它们是一个术语重写系统,但这种风格模糊了 LISP 对宏和函数的清晰区分。

CPP 的 #define 不等效,因为它不安全或不卫生(语法上有效的程序在预处理后可能变得无效)。

我们还可以根据需要为现有函数定义临时子句,例如。

plus (times x y) (times x z) = times x (plus y z)

另一个实际考虑是如果我们想要确定性结果,重写规则必须是confluent,即。无论我们应用规则的顺序如何,我们都会得到相同的结果。没有算法可以为我们检查这一点(通常是无法确定的),并且搜索空间太大,单个测试无法告诉我们太多信息。相反,我们必须通过一些正式或非正式的证明来说服自己,我们的系统是融合的;一种方法是遵循已知的融合系统。

例如,已知 beta-reduction 是合流的(通过 Church-Rosser Theorem),所以如果我们以 beta-reduction 的样式编写所有规则,那么我们可以确信我们的规则是合流的。当然,这正是函数式编程语言所做的!

【讨论】:

  • 检查许多示例不是确保融合的有效方法,无论是手动还是自动完成。证明需要从规则本身推导出来,可以是非正式的(例如,像“这是汇合的,因为函数组合是关联的”这样的评论)或正式的(例如,使用元逻辑中的模型,例如 Coq)。跨度>
  • 这是一个非常酷的答案。我留下了一个稍微精致的问题:如果没有相分离,什么时候(像这样的语言) Pure 做低级操作的“有用工作”,比如添加两个数字,如果 + always 充当返回可检查值的构造函数,并且每个函数调用实际上都是 match+cons?还是允许将整数数学和循环等低级概念引入语言基本上只是与基础理论无关的临时事物? (我可能应该首先尝试通过一种替代范式来理解它。)
  • 并不是“+”充当“构造函数”,而是所有术语都只是根本不“起作用”的愚蠢符号。所有工作都由重写引擎执行,它选择接下来应用哪个规则并执行重写。至关重要的是,所有控制流都是全局的:“+”不需要“决定”是将其参数简化为结果还是让它们“可检查”以供其他规则使用;所有这些都由重写引擎本身控制。
  • 可以在 REPL 中使用术语重写来为我们编写程序,但是我们可以使用术语重写将它们变成函数式程序。
猜你喜欢
  • 1970-01-01
  • 2011-02-02
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多