首页 文章

纯度与参考透明度

提问于
浏览
51

这些术语似乎有不同的定义,但我总是想到一个暗示另一个;当表达式是引用透明而不是纯粹或 vice-versa 时,我无法想到任何情况。

维基百科为这些概念维护单独的文章并说:

来自参考透明度

如果表达式中涉及的所有函数都是纯函数,则表达式是引用透明的。此外,如果丢弃它们的值并且它们的副作用无关紧要,则表达式中可以包含一些不纯的函数。

来自纯粹的表达

构造纯表达式需要纯函数。 [5]纯表达通常被称为引用透明。

我发现这些陈述令人困惑。如果来自 so-called“不纯函数”的副作用不足以允许不执行它们(i.e.用它的值替换对这样的函数的调用)而不实质性地改变程序,它就像它在第一个中是纯的一样地方,不是吗?

有没有更简单的方法来理解纯表达式和引用透明的表达式之间的差异(如果有的话)?如果存在差异,则可以理解清楚地表明它的示例表达。

5 回答

  • 40

    如果我在一个地方聚集了我认识的三位理论家,其中至少有两位不同意“参照透明度”一词的含义。当我还是一名年轻学生时,我的导师给了我一篇论文,解释说即使你只考虑专业文献,“引用透明”这个短语也用来表示至少三种不同的东西。 (不幸的是,这篇论文是在一个尚未被扫描的重印版中的某个地方.我在 Google 学术搜索中搜索了它,但我没有 success.)

    我不能告诉你,但我可以建议你放弃:因为即使是那些语言理论家的小干部也不能就它的意思达成一致,“引用透明”这个词并不是很有用**。所以不要使用它。


    P.S。关于与编程语言的语义有关的任何主题,维基百科都是不可靠的。我放弃了试图解决它;维基百科的过程似乎关注稳定性和准确性的变化和普遍投票。

  • 7

    所有纯函数都必须是引用透明的。根据定义,由于他们无法访问除传递内容之外的任何内容,因此他们的结果必须完全由他们的参数决定。

    但是,有可能具有不纯粹的引用透明功能。我可以编写一个给定 int i的函数,然后生成一个随机数r,从自身中减去r并将其放在s中,然后返回i - s。很明显,这个功能是不纯的,因为它产生随机数。但是,它是参考透明的。在这种情况下,这个例子很愚蠢和做作。但是,在 e.g. ,Haskell 中,id函数的类型为a - > a,而我的stupidId函数的类型为a -> IO a,表示它使用了副作用。当程序员可以通过外部证明保证他们的功能实际上是引用透明的时候,那么他们就可以使用unsafePerformIO从类型中剥离IO

  • 4

    我有点不确定我在这里给出的答案,但肯定会有人指出我们在某个方向。 :-)

    “纯度”通常被认为是指“缺少 side-effects”。如果一个表达式的评估缺乏 side-effects,那么它就是纯粹的。那是什么 side-effect?在纯粹的函数式语言中,side-effect 是任何不通过简单 beta-rule 的东西(评估函数应用程序的规则与替换形式参数的所有自由出现的实际参数相同)。

    例如,在具有线性(或唯一性,此时此区别不应该打扰)的函数式语言中,允许某些(受控)突变类型。

    所以我想我们已经找出了“纯度”和“side-effects”的含义。

    参考透明度(根据你引用的维基百科文章)意味着变量可以被表示的表达式(缩写,代表)替换而不改变手头程序的含义(顺便说一句,这也是一个难以解决的问题,并且我不会在这里尝试这样做)。因此,“纯度”和“参照透明度”确实是不同的东西:“纯度”是某种表达的属性,大致意味着“在执行时不产生 side-effects”而“参照透明度”是指与变量和表达有关的属性。 for 和 means 表示“变量可以用它表示的内容替换”。

    希望这会有所帮助。

  • 1

    这些幻灯片来自一个 ACCU2015 谈话对参考透明度这一主题有一个很好的总结。

    从其中一张幻灯片:

    如果(a)每个子表达式都可以被任何与其相等的值替换,并且(b)在给定上下文中出现的所有表达式产生相同的值,则语言在引用上是透明的。

    例如,您可以将一个将其计算记录到程序标准输出的函数(因此,它不是纯函数),但您可以通过不记录其计算的类似函数替换对此函数的调用。 。因此,此函数具有引用透明属性。但是......上面的定义是关于语言,而不是表达,正如幻灯片所强调的那样。

    [14]它就像它首先是纯净的一样,不是吗?

    根据我们的定义,不,它不是。

    有没有更简单的方法来理解纯表达式和引用透明的表达式之间的差异(如果有的话)?

    试试我上面提到的幻灯片

  • -1

    我将引用 John Mitchell 在他的书编程语言中的概念中所写的内容。我不记得它一行一行,但他定义纯函数式语言必须通过声明性语言测试,即:

    “在 x1,...,xn 的特定减速范围内,所有出现的仅包含变量 x1,...,xn 的表达式 e 具有相同的值。”

    简而言之,其他人都提到免于 side-effects 或没有副作用(副作用“缺乏”)。

    在语言学中,如果名称或名词短语可以被具有相同指示物的另一个名词短语替换而不改变其包含的句子的含义,则该名称或名词短语被认为是引用透明的。

    在第一种情况下,但在第二种情况下它变得太奇怪了。

    案例 1:“我看到沃尔特进入他的新车**。”

    如果沃尔特拥有一个 Centro,那么我们可以在给定的句子中替换为:

    “我看到沃尔特进入他的中心

    与第一个相反:

    案例#2:由于他的胡子,他被称为威廉·鲁弗斯**。

    Rufus 意味着有点红,并且引用了英格兰的威廉四世。

    “由于他的胡子,他被称为威廉四世**。”看起来太尴尬了。

    传统的说法是,如果我们可以在程序中的任何地方将一个表达式替换为具有相同值的另一个表达式而不改变程序的含义,则该语言是引用透明的。

    因此,引用透明度是纯函数式语言的属性。如果您的程序没有副作用,那么此属性将保留。

    所以放弃它是很棒的建议,但是在这种情况下,它可能看起来也很好。

相关问题