什么是参照透明性?


285

参照透明性一词是什么意思?我听说它被描述为“这意味着您可以用相等替换相等”,但这似乎是一个不足的解释。


1
哇,我想知道为什么这个问题的受欢迎程度突然激增……
Claudiu

1
@claudia:我不能肯定地说,但是r / haskell受到欢迎,许多人认为Uday虽然很准确,但在社区中有点嘲讽。
埃弗里(Efrey)2012年

6
@efrey一个吉伯,也许是。但是,当函数式程序员否决命令式编程语言而产生副作用的函数式语言(例如Lisp和ML)声称它们不是参照透明的时,他们是否会采取嘲讽的态度?他们是否应该至少在这样做之前弄清事实真相?
Uday Reddy

2
@Claudiu我一直在将其发布在Haskell Reddit上,而Conal在发推文。我发现讨论很有趣,并认为值得进行更广泛的讨论。我提请注意乌代(Uday)的风度来激发讨论。我同意,我们的FPer有时有时会沾沾自喜,并需要一个好的产品-为Uday提供的产品做得很好!
chrisdornan

7
@efrey。的确,这就是为什么我选择在第二篇文章中引用Bird和Wadler(语义学家?)的原因。知识渊博的人确实知道,引用透明性的流行概念是模糊的,甚至可能是不一致的。但是它从来没有适当地向编程社区解释过。希望我在这里的写作会有所作为。
Uday Reddy 2012年

Answers:


362

术语“参照透明性”来自分析哲学,这是哲学的分支,它基于逻辑和数学方法分析自然语言的构造,陈述和论点。换句话说,它是计算机科学之外最接近我们所谓的编程语言语义学的主题。哲学家威拉德·奎因Willard Quine)负责提出参照透明性的概念,但在伯特兰·罗素(Bertrand Russell)和阿尔弗雷德·怀特黑德(Alfred Whitehead)的研究方法中也隐含了这一点。

从本质上讲,“参照透明”是一个非常简单而清晰的想法。在分析哲学中,术语“指代物”用于谈论表达式所指的东西。它与我们在编程语言语义中所说的“含义”或“表示”大致相同。以安德鲁·伯克特(Andrew Birkett)的例子(博客文章)为例,“苏格兰的首都”一词指的是爱丁堡市。那是“指称”的简单例子。

如果用引用同一实体的另一个术语替换上下文中的术语,则该句子中的上下文是“相对透明的” 。例如

苏格兰议会在苏格兰首都举行会议。

与...相同

苏格兰议会在爱丁堡举行会议。

因此,“苏格兰议会在……开会”这一上下文是参照透明的上下文。我们可以用“爱丁堡”代替“苏格兰的首都”,而无需改变含义。换句话说,上下文仅关心该术语所指的内容,而无所谓。这就是上下文“相对透明”的意义。

另一方面,在句子中

自1999年以来,爱丁堡一直是苏格兰的首都。

我们不能做这样的替换。如果这样做的话,我们将得到“爱丁堡自1999年以来就是爱丁堡”的说法,这是胡说八道,并不传达与原始句子相同的含义。因此,上下文“爱丁堡自1999年以来……”是参照透明的(与参照透明相反)。显然,它关心的不仅仅是该术语所指的东西。它是什么?

诸如“苏格兰首都”之类的事物被称为定冠词,它们在很长一段时间内都没有给逻辑学家和哲学家带来任何头痛。罗素(Russell)和奎因(Quine)对它们进行了分类,说它们实际上不是“引用”,即认为上述示例用于引用实体是错误的。理解“爱丁堡自1999年以来就是苏格兰的首都”的正确方法是

苏格兰自1999年以来就有首都,而首都是爱丁堡。

这句话不能转化为坚果味。问题解决了!Quine的意思是说,自然语言是杂乱的,或者至少是复杂的,因为它使语言易于实际使用,但是哲学家和逻辑学家应该以正确的方式理解它们,以使其清晰。参照透明性是一种用于带来这种意义清晰的工具。

这一切与编程有什么关系?实际上不是很多。如前所述,参照透明性是一种用于理解语言(即分配含义)的工具。 创立编程语言语义学领域的Christopher Strachey将其用于意义研究中。他的基础论文“ 编程语言的基本概念 ”可以在网上找到。这是一篇漂亮的论文,每个人都可以阅读和理解。所以,请这样做。您将大开眼界。他在本段中引入了“参照透明性”一词:

表达式最有用的属性之一是Quine引用透明性所调用的属性。从本质上讲,这意味着如果我们希望找到包含子表达式的表达式的值,那么关于子表达式我们唯一需要了解的就是它的值。子表达式的任何其他特征,例如其内部结构,其组成部分的数量和性质,评估它们的顺序或书写它们的墨水颜色,均与主体的值无关。表达。

“本质上”的使用表明Strachey对其释义,以便用简单的术语进行解释。函数式程序员似乎以自己的方式理解本段。本文中还有9个“参照透明性”的出现,但它们似乎并不在乎其他任何一个。实际上,Strachey的整个论文都致力于解释命令式编程语言的含义。但是,今天,函数式程序员声称命令式编程语言不是引用透明的。Strachey会在坟墓里转弯。

我们可以挽救局势。我们说自然语言是“混乱的,或者至少是复杂的”,因为它使实用方便。编程语言是相同的方式。它们是“混乱的,或至少是复杂的”,因为它们被制成便于实际使用。这并不意味着他们需要使我们感到困惑。只需要使用一种引用透明的元语言就可以正确地理解它们,以便我们清楚地理解含义。在我引用的论文中,Strachey正是这样做的。他通过将命令式编程语言分解为基本概念来解释命令式编程语言的含义,从不丧失任何地方的清晰度。他的分析的重要部分是指出编程语言中的表达式具有两种“值”,r值。在Strachey的论文发表之前,这还不为人所知,混乱至高无上。如今,C的定义已定期提及它,并且每个C程序员都理解这一区别。(很难说其他语言的程序员是否同样理解它。)

Quine和Strachey都关心涉及某种形式的上下文相关的语言构造的含义。例如,我们的示例“爱丁堡自1999年以来一直是苏格兰的首都”表明“苏格兰的首都”取决于考虑该城市的时间这一事实。无论是自然语言还是编程语言,这种上下文相关性都是现实。即使在函数式编程中,自由变量和绑定变量也要针对它们出现的上下文进行解释。任何种类的上下文相关性都会以某种方式阻止参照透明性。如果您在不考虑术语所依赖的上下文的情况下尝试理解术语的含义,则会再次陷入混乱。Quine关心模态逻辑的含义。他认为模态逻辑是参照不透明的,应通过将其转换为参照透明的框架(例如,将必要性视为可证明性)进行清理。他很大程度上失去了这场辩论。逻辑学家和哲学家都发现,克里普克的可能世界语义学是完全合适的。强制性编程也存在类似情况。Strachey解释的状态依赖和Reynolds解释的存储依赖(以与Kripke可能的世界语义类似的方式)完全足够。函数式程序员对此研究并不了解。他们关于参照透明性的想法要花大量的盐。

[附加说明:以上示例说明了一个简单的词组,例如“苏格兰首都”,具有多种含义。一方面,我们可能正在谈论当前的资本。在另一个层面上,我们可能会谈论苏格兰在一段时间内可能拥有的所有可能的首都。在正常实践中,我们可以“放大”特定的上下文,并“缩小”以轻松跨越所有上下文。自然语言的效率利用了我们的能力。命令式编程语言以几乎相同的方式有效。我们可以在赋值(r值)的右侧使用变量x来讨论其在特定状态下的值。或者,我们可能会谈论它的L值跨越所有州。人们很少被这种事情弄糊涂。但是,他们可能无法也可能无法准确地解释语言构造所固有的所有含义层。所有这些含义层不一定都是“显而易见的”,正确研究它们是科学问题。但是,普通人解释这种分层含义的含蓄态度并不意味着他们对此感到困惑。

以下单独的“后记”使此讨论与功能和命令式编程有关


10
谢谢,但我不认为有一个“明显的”平等扩展概念。当我说“苏格兰的首都”指的是爱丁堡市时,您对此并没有三思而后行。但是,当我开始谈论“自1999年以来”时,您突然意识到需要花费一些时间。因此,平等的可扩展性概念可能非常微妙,并且由编程语言研究人员将其形式化。希望对扩展性平等有完美理解的人们需要学习这项研究的成果。它可能根本不是“显而易见的”。
Uday Reddy 2012年

5
太棒了!欢迎消除对RT的普遍误解,例如将其与功能相关联。或通过用表达式的值替换表达式来进行定义(如Wikipedia上那样),这很奇怪,因为表达式和值是不同的事物。人们在考虑命令式语言的RT-性时可能出错的一个地方是,假设这些“值”是简单的事物(例如数字),而不是更复杂的事物(例如商店中的函数)。
圆锥

13
@sclv关于分析哲学对计算机科学的更广泛影响,我应该说,众所周知,计算机科学是由Godel,Church,Kleene和Turing创建的。这些人是逻辑学家,他们精通逻辑的数学和哲学方面,尤其是Peano,Frege,Russell,Whitehead,Carnap和Quine的传统。现代计算机科学的早期开拓者知道这种联系。但是计算机科学的迅速发展使它们断绝了。我们需要回到他们那里。
Uday Reddy

5
@sclv逻辑传统上被认为是结果科学。但是我认为它是更广泛的。这是信息科学。奎因,我是第一个提出更广泛观点的人。“单词和对象”是对自然语言陈述的信息内容的分析。然而,考虑到远古时代以来,文明和科学的中心计算已成为主流,因此哲学家和数学家都从未对计算产生过积极的兴趣,这是相当令人困惑的。我们需要找到使他们感兴趣的方法。
Uday Reddy

3
@Conal:我添加了一个新的答案,可以扩大您的观点。它可能会在页面底部。
Uday Reddy

134

引用透明性,在函数式编程中通常使用的一个术语,意味着给定一个函数和一个输入值,您将始终收到相同的输出。也就是说,函数中没有使用外部状态。

这是引用透明函数的示例:

int plusOne(int x)
{
  return x+1;
}

使用参照透明函数(给定输入和函数),您可以将其替换为值,而不用调用函数。因此,不用用参数5调用plusOne,我们可以将其替换为6。

另一个很好的例子是数学。在给定函数和输入值的数学中,它将始终映射到相同的输出值。f(x)= x +1。因此,数学函数是参照透明的。

这个概念对研究人员很重要,因为它意味着当您具有参照透明功能时,它很容易实现自动并行化和缓存。

引用透明性始终在Haskell这样的功能语言中使用。

-

相反,存在参照不透明的概念。这意味着相反。调用该函数可能并不总是产生相同的输出。

//global G
int G = 10;

int plusG(int x)
{//G can be modified externally returning different values.
  return x + G;
}

另一个示例是面向对象编程语言中的成员函数。成员函数通常对其成员变量进行操作,因此将是引用不透明的。成员函数当然可以是参照透明的。

另一个示例是从文本文件读取并打印输出的函数。该外部文本文件可以随时更改,因此该功能将是不透明的。


1
只需抬起头,就有可能拥有一个完全参照透明的对象,并具有参照透明的成员函数。参见okmij.org/ftp/Scheme/oop-in-fp.txt
Jonathan Arkell,

1
这是该文章中讨论的代码:okmij.org/ftp/Scheme/pure-oo-system.scm
Jonathan Arkell,

对于完全引用透明的类,可能所有成员函数都是静态的。
布赖恩·邦迪

13
您在这里谈论的不是参照透明性,尽管通常被称为参照透明性。请参阅Uday的两个答案以及对其的评论。特别是,您所谓的“输出”不是外延。如果将“ plusG 3”替换为具有相同值/符号的任何其他表达式,则您确实会获得具有相同含义的程序,因此RT确实适用于命令式语言。表述“3 + 10”或“13” 具有相同的含义为“plusG 3”,因为在命令式语言意为“存储”(状态)的功能。
Conal 2012年

1
我刚刚读了一篇有关副作用和状态变化的文章,直觉上认为它与RT有关。你能在上面加个注释吗?
Gaurav 2015年

91

参照透明功能是仅依赖于其输入的功能。


4
这就是为什么在OO编程中很难实现的原因,因为对象具有状态。
克里斯(Kris)

5
那么在描述函数时说“参照透明”与“确定性”相同是正确的吗?如果不是,这两个术语有什么区别?
mwolfe02 '06

1
这听起来也像是“纯”函数的定义。
Evgeny A.

75

[这是我3月25日以来的回答的后记,以使讨论更接近功能/命令式编程的关注。]

函数式程序员的引用透明性思想似乎与标准概念在以下三个方面有所不同:

  • 哲学家/逻辑学家使用诸如“引用”,“表示”,“ designatum”和“ bedeutung ”(弗雷格的德语术语)之类的术语,而功能程序员则使用“值”一词。(这不完全是他们的工作。我注意到,Landin,Strachey及其后代也使用“值”一词来谈论参考/表示。这可能只是Landin和Strachey引入的术语简化,但似乎使天真地使用时有很大的差异。)

  • 函数式程序员似乎相信这些“值”存在于编程语言中,而不是外部。在此过程中,他们既不同于哲学家,也不同于编程语言语义学家。

  • 他们似乎认为这些“值”应该通过评估获得。

例如,维基百科上有关参照透明性的文章说,今天早上:

如果可以在不更改程序行为的情况下将其替换为其值(换句话说,产生具有相同效果并在相同输入上输出的程序),则该表达式被称为参照透明的。

这与哲学家/逻辑学家所说的完全不同。他们说,一个上下文是参考或引用透明如果在该上下文中的表达可通过另一替换表达式引用同样的事情(一个共指表达)。这些哲学家/逻辑学家是谁?它们包括FregeRussellWhiteheadCarnapQuineChurch还有无数其他人 他们每个人都是高大的人物。至少可以说,这些逻辑学家的综合才智令人震惊。他们都是一致的立场,即语言只能说说内正式语言和表达外存在所指/ denotations 他们。因此,该语言所能做的就是将一个表达式替换为引用同一实体的另一个表达式。语言中存在引用对象/代名词。为什么函数式编程人员会偏离这种公认的传统?

人们可能会认为编程语言语义学家可能误导了他们。但是,他们没有。

兰丁

(a)每个表达式都有一个嵌套子表达式结构,(b)每个子表达式都 表示某种东西(通常是数字,真值或数值函数),(c)表达式表示的东西,即其“值”,仅取决于它的子表达式的值,而不是它们的其他属性。[增加重点]

斯托伊

表达式唯一重要的是它的值,任何子表达式都可以用任何其他相等的值代替[增加重点]。而且,表达式的值在一定范围内在出现时是相同的。”

鸟和沃德勒

表达式的值仅取决于其组成表达式的值(如果有),并且这些子表达式可以自由地由具有相同值其他表达式替换[增加重点]。

因此,回想起来,Landin和Strachey通过用“值”替换“参考” /“符号”来简化术语的努力可能是有害的。一旦听到“价值”,就会想起一个导致它的评估过程。同样很容易想到将评估产生的任何内容都视为“值”,即使可能已经很清楚地知道这并非其含义。在函数式程序员看来,这就是我碰到的“参照透明”概念。但是,早期语义学家所说的“价值” 不是功能或任何类似事物的评估或输出的结果。这是该术语的含义。

一旦我们将表达的所谓“价值”(古典哲学家话语中的“指称”或“指称”)理解为一个复杂的数学/概念性对象,就会出现各种可能性。

  • 正如我在3月25日的回答中提到的那样,Strachey将命令式编程语言中的变量解释为L值,这是一个复杂的概念对象,在编程语言的语法中没有直接表示。
  • 他还使用状态对状态函数之类的语言来解释命令,这是语法中不是“值”的复杂数学对象的另一个实例。
  • 甚至C语言中的副作用函数调用也具有定义明确的“值”作为状态转换器,它将状态映射到成对的状态和值(在函数程序员的术语中称为“ monad”)。

函数式程序员不愿将此类语言称为“相对透明”,仅表示他们不愿将此类复杂的数学/概念对象视为“值”。另一方面,当状态转换程序使用自己喜欢的语法并用诸如“ monad”之类的时髦词修饰时,他们似乎非常愿意将状态转换程序称为“值”。我必须说,他们完全不一致,即使我们同意他们的“参照透明性”观念具有一定的连贯性。

一段历史可能会揭示这些混乱是如何产生的。对于克里斯托弗·斯特拉奇(Christopher Strachey)而言,1962年至1967年是一个非常密集的时期。1962-65年间,他在Maurice Wilkes担任兼职研究助理,以设计和实现后来被称为CPL的编程语言。这是一种命令式编程语言,但也具有强大的功能性编程语言功能。Landin是Strachey在其咨询公司的雇员,他对Strachey的编程语言观点产生了巨大的影响。在1965年具有里程碑意义的论文“ 下一种700种编程语言 ”中,Landin毫不掩饰地推广了函数式编程语言(称其为表示性语言)语言),并将命令式编程语言描述为它们的“对立面”。在随后的讨论中,我们发现Strachey质疑Landin的强势地位。

... DL构成所有语言的子集。它们是一个有趣的子集,但是除非您习惯了,否则使用起来很不方便。我们需要它们,因为目前我们还不知道如何使用包括命令和跳转在内的语言构造证明。[增加重点]

1965年,斯特拉奇(Strachey)担任牛津大学(Oxford)的读者一职,似乎基本上全职致力于发展命令式和跳跃式理论。到1967年,他已经准备好了一种理论,并在哥本哈根的一所夏季学校的“ 编程语言的基本概念 ”课程中教授了这一理论。这些讲义原本应该已经出版​​了,但是“不幸的是,由于进行了漫长的编辑,会议记录从未得以实现;然而,就像Strachey在牛津大学所做的许多工作一样,该论文也具有影响力。” (马丁·坎贝尔·凯利

很难获得Strachey的著作,这可能会导致混乱的传播,人们不得不依赖次要来源和传闻。但是,既然“ 基本概念 ”已经可以在网络上找到,那么就无需诉诸猜测了。我们应该阅读它,并对Strachey的含义下定决心。特别是:

  • 在3.2节中,他讨论了“表达式”,其中谈到了“ R值参照透明性”。
  • 他的第3.3节处理“命令”,其中讨论“ L值参照透明性”。
  • 在第3.4.5节中,他讨论了“函数和例程”,并声明“应该通过将表达式分解为几个命令和更简单的表达式来消除R值引用透明性在R值上下文中的任何偏离。评论的事实证明这很困难。”

从根本上讲,在不理解L值,R值和其他构成命令式程序员概念范围的复杂对象之间的区别的情况下,谈论“参照透明性”是错误的。


10
我认为值得强调的是,混淆这两个“值”(评估与表示)概念会误导函数式程序员对命令式语言的批评,因为命令式语言之间的差距很大。
圆锥

8
也就是说,评估概念得出这样的结论:命令性语言不是RT,而指示语言不是RT。
康那,

12
在我看来,一旦您完全确定了一种语言的指称语义,它便会无比透明。因此,这似乎等于说该术语对编程语言没有用。
汤姆·克罗基特

20
因此,似乎人们习惯于使用一个术语来指代与其他人过去使用该术语时所指的实质不同的含义。我要说的是:欢迎使用英语。
丹尼尔·普拉特

17
@DanielPratt:如果说副作用自由是功能程序员要表达的意思,那么为什么他们称其为“参照透明性”呢?他们可以称其为“副作用自由”,这是一个非常明确的想法。任何人都不需要在stackexchange上询问“副作用自由”是什么意思。哪里需要弄清似乎没人能理解的宏伟经典术语?
Uday Reddy

23

如果表达式可以用其值替换,而无需更改算法,则该表达式是参照透明的,从而产生具有相同效果并在相同输入上输出的算法。


18

参照透明函数是一种类似于数学函数的函数。给定相同的输入,它将始终产生相同的输出。这意味着传入的状态没有被修改,并且该函数没有自己的状态。


10

对于那些需要简要说明的人,我将予以警告(但请阅读以下披露内容)。

编程语言中的参照透明性促进了方程式推理-参照透明性越多,进行方程式推理就越容易。例如,(伪)函数定义,

fx = x + x,

在此定义的范围内,可以轻松(安全地)用foo + foo替换f(foo),而对执行此还原的位置没有太多限制,这很好地表明了编程语言的引用透明性已。

例如,如果foo在C编程意义上是x ++,那么您将无法安全地执行此还原操作(也就是说,如果要执行此还原操作,您将不会得到与开始时相同的程序)。

在实际的编程语言中,您不会看到完美的引用透明性,但是函数式程序员比大多数人更关心它(请参阅Haskell,它是核心目标)。

(完全公开:我是一名函数程序员,因此,最重要的答案是您应该对这种解释有所保留。)


3
我对促进方程式推理的语言没有任何疑问。但是我会争辩说,这与经典定义的“参照透明性”有关。其次,作为一名实用的程序员,我认为方程式推理被高估了。在实践中重要的推理与前置条件,后置条件,不变式和数据抽象有关。对于依靠这种推理技术的人来说,副作用似乎并不重要。因此,虽然我同意您的观点,但表达式中的副作用不是一个好主意,但它们似乎并不代表杀手argument。
Uday Reddy

1
@UdayReddy仅仅是因为函数式程序员选择了一种特殊的方法来提高程序中的参照透明性(消除副作用并开发程序的复杂而强大的代数),或者有些从业者可能不了解参照透明性,并且他们认为确实如此,这并不意味着函数式编程语言无法提高引用透明性,也不意味着函数式语言程序员和编译器作者并未将这种形式可扩展性的提高用于许多目的。
chrisdornan

2
克里斯(Chris):乌代(Uday)指出,斯特拉奇(Strachey)消除了编程语言语义中的引用不透明性的问题,特别是对于命令式语言。因此,函数式程序员不能“在其程序中增加参照透明性”。举一个具体的例子,Haskell IO确实对RT没有帮助,因为不需要RT帮助。
Conal 2012年

2
@chrisdornan:对不起,我在上面的第一条评论。我本人很难理解我在前两句话中要说的内容:-(但是,这是一种解释。考虑两级或多级登台演算。每个登台运算符都是参照不透明的。实际上,报价运营商然而,您可以在每个阶段内做等式推理完全正常所以,每个指称不透明的运营商建立了等式推理的界限,但你还是得在这些边界内等式推理。
乌代·雷迪

1
@chrisdomain:而且,很少有人会希望成为透明的参照透明派人士,以便消除此类登台算子。这些运算符非常有用。如果不通过手动执行登台操作来进行编程,则将是乏味,容易出错且丑陋的。而且,手动进行暂存不会比以前拥有更多的等式推理。因此,在纯粹追求方程式推理的过程中禁止使用良好的编程设备就好比割断鼻子来掩饰自己的脸。
Uday Reddy


4
  1. 指称语义是通过建立构成可表值的域的基础上对语言进行建模的。
  2. 功能程序员使用术语“ 值”来描述基于语言重写规则(即)的计算收敛性。它的操作语义。

在[1]中,两种语言都有明确的含义:

  • 被建模的对象语言
  • 建模语言,元语言

2,由于对象和金属语言的接近性,它们可能会混淆。

作为语言实施者,我发现我需要不断记住这一区别。

因此,雷迪教授,我可以这样解释:-)

在功能编程和语义的上下文中,术语“ 参照透明性”不是参照透明的。


1
哈哈。感谢您的解释。问题还在于,函数式程序员的行为就像他们具有适用于所有编程语言的“引用透明性”的一般概念一样。但这取决于他们的“价值”概念,这对其他语言可能有意义,也可能没有意义。要主张“参照透明性”的一般理论,他们需要产生一般理论的“价值”。到目前为止,这是缺少的。
Uday Reddy

4

我希望以下答案可以补充并限定有争议的第一和第三答案。

让我们同意一个表达式表示或指代某个引用对象。但是,一个问题是,这些引用对象是否可以作为表达式本身的一部分进行同构编码,从而将此类表达式称为“值”。例如,文字数字值是算术表达式集的子集,真值是布尔表达式集的子集,依此类推。其想法是将表达式评估为其值(如果有一个值)。因此,“值”一词可以指代表达式集中的一个符号或一个可区分的元素。但是,如果引用对象和值之间存在同构(双射),则可以说它们是同一件事。(这就是说,必须谨慎定义引用对象和同构,这已经由指称语义学领域证明。data Nat = Zero | Suc Nat 不符合预期的自然数集。)

让我们来写E[·]一个带有洞的表达式,在某些情况下也被称为“上下文”。类C表达式的两个上下文示例是[·]+1[·]++

让我们[[·]]为在某个提供含义的世界中编写一个带有表达式(不带孔)并传递其含义(引用,表示等)的函数编写。(我从指称语义学领域借用了表示法。)

让我们在某种程度上正式地修改Quine的定义,如下所示:E[·] 如果给定了两个表达式E1并且E2(那里没有孔),则上下文是参照透明的,[[E1]] = [[E2]]即(表达式表示/引用相同的引用对象)则是这样的情况[[E[E1]]] = [[E[E2]]](即填充-在孔中使用或E1或,E2结果也表示相同的参照物)。

莱布尼兹用“等于”代替“等于”的规则通常表示为“ if E1 = E2then E[E1] = E[E2]”,即E[·]函数。一个功能(或为此功能计算程序的功能)是从源到目标的映射,因此每个源元素最多有一个目标元素。非确定性函数是错误的名词,它们要么是关系,要么是函数传递集合,等等。如果按照莱布尼兹的规则,相等性=是指称的,那么双括号就被认为是理所当然的而被忽略了。因此,参照透明上下文是一个函数。莱布尼兹的规则是等式推理的主要组成部分,因此等式推理肯定与参照透明性相关。

尽管[[·]]它是从表达式到符号的函数,但它可以是从表达式到“值”的函数,[[·]]可以将其理解为表达式的受限子集,也可以理解为评估。

现在,if E1是一个表达式,并且E2是一个值,在定义表达式,值和评估的参照透明性时,我认为大多数人都具有这个意思。但是,如本页第一和第三答案所示,这是一个不准确的定义。

诸如此类的上下文问题[·]++并不是副作用,而是C的值没有按照其含义同构地定义。函数不是值(嗯,指向函数的指针是),而在函数式编程语言中则是。Landin,Strachey和指称语义学的先驱在使用功能世界提供含义方面非常聪明。

对于类似C的命令式语言,我们可以使用函数大致为表达式提供语义[[·]] : Expression -> (State -> State x Value)

Value是的子集ExpressionState包含对(标识符,值)。语义函数采用表达式并将其含义从当前状态传递到具有更新状态和值的对。例如,[[x]]是从当前状态到一对的函数,其第一部分为当前状态,第二部分为x的值。相反,[[x++]]是从当前状态到该对的函数,其第一分量是x的值递增的状态,而第二分量就是该值。从这个意义上讲,如果上下文[·]++满足上面给出的定义,则上下文是参照透明的。

我认为函数式程序员有权使用引用透明性,因为它们可以自然地[[·]]作为函数从表达式恢复为值。函数是一等值,状态也可以是值,而不是符号。状态monad(部分地)是一种用于传递(或线程化)状态的干净机制。


大概“第一”和“第三”的答案分别是UdayReddy的“ 3月25日”和“后记”的答案。普通语言不是在SO中引用答案的好方法。投票和接受不仅会随着时间而改变,而且还有多种可选顺序。
philipxy

2

注意,“意义”的概念是在观察者心中发生的。因此,相同的“参考”对于不同的人可能意味着不同的事物。因此,例如,我们在Wikipedia中有一个爱丁堡歧义消除页面。

在编程环境中可能出现的一个相关问题可能是多态。

也许我们应该为多态现象的特殊情况起一个名字(或者甚至是强制转换),其中出于我们的目的,不同的多态情况在语义上是等效的(而不是仅仅相似。例如,数字1-可以表示为使用整数类型,复杂类型或多种其他类型中的任何一种-可以进行多态处理)。



0

参照透明性可以简单地表示为:

  • 始终在任何上下文中都求值相同结果的表达式[1]
  • 如果函数两次被赋予相同的参数,则必须两次产生相同的结果[2]

例如,编程语言Haskell是一种纯函数式语言;意味着它是参照透明的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.