gpt4 book ai didi

functional-programming - Date.now引用透明吗?

转载 作者:行者123 更新时间:2023-12-04 08:40:57 26 4
gpt4 key购买 nike

DateTime.NowDate.now是引用透明的吗?

这是Qiita中的函数式编程文章中有争议的主题之一。

首先,我们必须非常小心,因为“参照透明”一词在某种意义上是棘手的词/概念,并且在

What is referential transparency?

发问者称:


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


一个非常典型的解释,但通常会导致我们误解的想法如下:(上一页的#2答案,@ Brian R. Bondy)


引用透明性,是函数编程中常用的术语,表示给定功能和输入值,您将始终收到相同的输出。也就是说,函数中没有使用外部状态。


我一直听到并认为错误的典型主张是这样的:

在编程语言中,Date.now始终返回与当前时间相对应的不同值,并且根据


给定一个函数和一个输入值,您将始终收到相同的输出。


因此,Date.now不是参照透明的!

我知道一些(函数式)程序员坚信上述主张是可信的,但是,@ Uday Reddy给出的#1和#3回答如下:


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

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



哲学家/逻辑学家使用诸如“引用”,“表示”,“ designatum”和“ bedeutung”(弗雷格的德语术语)之类的术语,而功能程序员则使用“值”一词。 (这不完全是他们的工作。我注意到,Landin,Strachey及其后代也使用“值”一词来谈论参考/表示。这可能只是Landin和Strachey引入的术语简化,但似乎使如果以幼稚的方式使用,则差异很大。)
函数式程序员似乎认为这些“值”存在于编程语言中,而不是外部。在此过程中,他们既不同于哲学家,也不同于编程语言语义学家。
他们似乎认为这些“值”应该通过评估获得。


想到这一点,“外部状态”也是一个棘手的词/概念。


引用透明性,是函数编程中常用的术语,表示给定功能和输入值,您将始终收到相同的输出。也就是说,函数中没有使用外部状态。


是“当前时间”是“外部状态”还是“外部价值”?

如果我们称“当前时间”为“外部状态”,那么“鼠标事件”呢?

“鼠标事件”不是应该由编程上下文管理的状态,而是一个外部事件。


给定一个函数和一个输入值,您将始终收到相同的输出。


因此,我们可以理解如下:

“当前时间”既不是“输入值”也不是“外部值”也不是“外部状态”,并且Date.now始终返回与正在进行的事件“当前时间”相对应的相同输出。

如果仍然坚持或想将“当前时间”称为“值”,那么,


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


“当前时间”的值从不存在于编程语言中,而仅存在于外部,而“外部时间”的值显然不是通过编程上下文而是通过真实世界的时间流来更新的。

因此,我了解Date.now是引用透明的。

我想读一下你的想法。谢谢。



编辑1


What is (functional) reactive programming?

Conal Elliott @Conal还解释了功能反应编程(FRP)。

他是最早开发FRP的人之一,他这样解释:


FRP是关于-“代表“时间”值的数据类型”
动态/不断变化的值(即“随时间变化的值”)本身就是一等值。


从FRP的角度来看,


Date可以看作是“随时间变化”的一等值,它是时间轴上的不变对象。
.now是用于在Date中解决“当前时间”的属性/功能

因此,Date.time返回表示我们“当前时间”的不可变和参照透明值。




编辑2

(在JavaScript中)

参照不透明函数

let a = 1;

let f = () => (a);


Function:f的输入为none;
Function:f的输出取决于 a,后者取决于 f以外的上下文

参照透明功能

let t = Date.now();

let f = (Date) => (Date.now());


尽管 Date值存在于我们的物理世界中,但 Date可以看作是“随时间推移”不变的FRP一流值。

由于从任何编程上下文引用的 Date都是相同的,因此我们通常会隐式地省略 Date作为输入值,就像

let f = () => (Date.now());




编辑3

实际上,我通过电子邮件发送给Conal Elliott @Conal,后者是FRP最早的开发者之一。
他友善地回答,并告诉我这里有一个类似的问题。

How can a time function exist in functional programming?

发问者称:


所以我的问题是:函数编程中是否可以存在一个时间函数(返回当前时间)?



如果是,那么它怎么存在?它不违反功能编程的原理吗?它特别违反了引用透明性,而引用透明性是函数式编程的属性之一(如果我正确理解的话)。
否则,如何知道函数式编程的当前时间?


并且,Conal Elliott @Conal在stackoverflow中的答案:


是的,如果给定时间作为参数,则纯函数有可能返回时间。不同的时间参数,不同的时间结果。然后还形成其他时间功能,并将它们与功能(时间)转换(高阶)函数的简单词汇结合起来。由于该方法是无状态的,因此此处的时间可以是连续的(与分辨率无关),而不是离散的,从而极大地提高了模块性。这种直觉是功能反应式编程(FRP)的基础。




编辑4
感谢@Roman Sausarnes的回答。

请允许我介绍我对函数式编程和FRP的看法。

首先,我认为编程从根本上讲是关于
数学和函数式编程都追求这一方面。在
另一方面,命令式编程是描述以下步骤的一种方法
机器操作,不一定是数学。

像Haskel这样的纯函数式编程很难处理
“状态”或IO,我认为整个问题都来自“时间”。

“状态”或“时间”几乎是我们人类的主观实体。我们
自然地相信“时间”在流逝或流逝,而“状态”是
变化,即 Naïve realism

我认为“时间”的朴素现实主义是根本的危害,也是
编程社区中所有的混乱,很少讨论
方面。在现代物理学中,甚至从牛顿物理学中,我们都对待时间
以纯数学的方式,所以如果我们以物理学的方式概述我们的世界,
用纯数学来对待我们的世界应该没有什么困难
功能编程。

因此,我概述了我们的世界/宇宙是不可变的,就像预先录制的DVD一样,
并且只有我们的主观观点是可变的,包括“时间”或“状态”。

在编程中,不变的宇宙与
我们可变的主观经验是“事件”。纯功能
诸如Haskell这样的编程语言基本上没有这种看法,
尽管包括科内尔·埃利奥特(Cornel Elliott)在内的一些有远见的研究人员都进行了FRP,但是大多数人仍然认为FRP方法仍然是次要的或难以使用的,而且他们中的许多人理所当然地认为是可变状态。

自然,FRP是唯一的智能解决方案,特别是作为创始人的Cornel Elliott运用了这种哲学观点,并宣布-首先
类值“随着时间的推移”。不幸的是,也许很多程序员
不会理解他的真正意思,因为他们被天真困住了
现实主义,很难从哲学上看待“时间”,或者
物理上不变的实体。

因此,如果他们讨论“纯功能性”或“参照透明性”
为了数学上的完整性/一致性,对我来说,
“ Date.now”在纯函数内自然是引用透明的
编程,仅仅是因为“ Date.time”访问了某个点
不可变宇宙的不可变时间线。



那么,诸如@Reddy或@Roman Sausarnes的贬义语义中的引用透明性又如何呢?

我概述了FP中的参照透明性,尤其是在Haskell社区中,这完全是关于数学完整性/一致性。

当然,也许我可以遵循Haskell社区对“参照透明性”的更新定义,并且实际上,如果我们判断该代码不是参照透明性的,那么我们认为代码在数学上是不一致的,对吗?

其实,再次

How can a time function exist in functional programming?

程序员提出以下问题:


所以我的问题是:函数编程中是否可以存在一个时间函数(返回当前时间)?



如果是,那么它怎么存在?它不违反功能编程的原理吗?它特别违反了引用透明性,而引用透明性是函数式编程的属性之一(如果我正确理解的话)。
否则,如何知道函数式编程的当前时间?




共识

违反函数式编程的原则

=违反了引用透明性,这是函数式编程的特性之一

=数学上不一致!!



这是我们的常识,对吗?

在这个问题中,许多人回答说“返回当前时间的函数”不是参照透明的,特别是在Haskell社区对“参照透明”的定义中,许多人提到这与数学一致性有关。

但是,只有少数人回答“返回当前时间的函数”是引用透明的,答案之一是Conal Elliott @Conal从FRP的角度出发。

IMO,FRP,将时间流作为“随时间变化”的一流不变值来处理的观点是一种正确的方式,具有如上所述的数学原理,例如物理。

那么,为什么Haskell上下文中的“ Date.now” /“返回当前时间的函数”变得不透明?

好吧,我能想到的唯一解释是Haskell社区对“参照透明性”的更新定义有些错误。

事件驱动和数学完整性/一致性

我提到过-在编程中,不变的宇宙和
我们可变的主观体验是“事件”或“事件驱动”。

函数式编程以事件驱动的方式进行评估,另一方面,命令式编程则通过以下步骤/例程进行评估:
代码中描述的机器操作。

“ Date.now”取决于“事件”,原则上,代码上下文不知道“事件”。

那么,事件驱动会破坏数学完整性/一致性吗?绝对不。

将语法映射到含义-索引(食指)

C.S. Peirce introduced the term ‘indexical’ to suggest the idea of pointing (as in ‘index finger’)。 ⟦I⟧,[[这里]],[[现在]]等。

在数学上,这可能是Haskell中“ Monad”,“ functor”事物的数学上相同的概念。在指称语义中,甚至在Haskell中,[[now]]作为“食指”也很清楚。

食指(食指)是主观的,事件驱动也是主观的

[[I]],[[here]],[[now]]等是主观的,在编程中,不变的客观宇宙与
我们可变的主观体验是“事件”或“事件驱动”

因此,我认为,只要[[now]]绑定到“事件驱动”编程的事件声明,就永远不会发生主观(与上下文相关)数学上的不一致。



编辑5

@Bergi给了我一个很好的评论:


是的,外部值 Date.now是参照透明的。它始终表示“当前时间”。

但是 Date.now()不是,它是一个函数调用,根据外部状态返回不同的数字。具有参照透明性的“当前时间的概念”的问题在于我们无法用它来计算任何东西。

@KenOKABE:似乎与 Date.now()相同。
问题在于,这并不意味着当前时间是在同一时间,而是在不同的时间-程序需要花费时间才能执行,这就是使其不纯净的原因。

当然,我们可以设计一个参照透明的 Date.now函数/获取器,该函数始终返回程序启动的时间(就像程序立即执行一样),但这不是 Date.now()/Date.Now的工作方式。它们取决于程序的执行状态。 –贝吉


我认为我们需要讨论它。

外部值 Date.now是参照透明的。

[[Date.now]]就像我在#Edit4中提到的那样,它是主观的食指(食指),但是只要它保留在食指域中(无需执行/评估),它就是参照透明的,我们同意上。

但是,@ Bergi建议 Date.now()(带有执行/评估)在不同的时间返回“不同的值”,并且不再是参照透明的。我们尚未达成共识。

我认为他确实显示了这个问题,但只存在于命令式编程中:

console.log(Date.now()); //some numeric for 2016/05/18 xx:xx:xx ....
console.log(Date.now()); //different numeric for 2016/05/18 xx:xx:xx ....


我同意,在这种情况下, Date.now()不是参照透明的。

但是,在函数式编程/声明式编程范例中,我们永远不会像上面那样写。我们必须这样写:

const f = () => (Date.now());


并且,该 f在某些“事件驱动”上下文中进行评估。这就是功能编程代码的行为方式。

是的,此代码与

const f = Date.now;


因此,在函数式编程/声明式编程范例中, Date.nowDate.now()(具有执行/求值)从没有问题,可以在不同的时间返回“不同的值”。

因此,再次,正如我在EDIT4中所提到的,只要[[now]]绑定到“事件驱动”编程的事件声明,我就不会发生主观(与上下文相关)数学上的不一致。

最佳答案

好吧,我要对此采取行动。我不是这方面的专家,但是我花了一些时间思考您链接到的@UdayReddy's answers to this question,我想我对此深信不疑。

分析哲学中的参照透明

我认为您必须从雷迪先生回答其他问题的位置开始。雷迪先生写道:


在分析哲学中,术语“指代物”用于谈论表达式所指的东西。它与我们在编程语言语义中所说的“含义”或“表示”大致相同。


注意单词“ denotation”的使用。编程语言具有语法或语法,但也具有语义或含义。 Denotational semantics是将语言的语法翻译成其数学含义的实践。

据我所知,指称语义虽然未被广泛理解,但它是围绕计算机程序进行理解,设计和推理的最强大的工具之一。我要花一点时间为您的问题的答案奠定基础。

指称语义:将语法映射到意义

指称语义背后的思想是,计算机语言中的每个语法元素都具有对应的数学含义或语义。指称语义是语法和语义之间的显式映射。取语法数字1。您可以将其映射为其数学含义,即数学数字1。语义函数可能如下所示:

syntax

⟦1⟧ ∷ One

semantics


有时双括号用于表示“含义”,在这种情况下,语义侧的数字 1被拼写为 One。这些只是指示我们何时谈论语义以及何时谈论语法的工具。您可以将该函数读为“语法符号 1的含义是数字 One”。

我上面使用的示例看起来很简单。当然, 1表示 One。还有什么意思呢?但这不是必须的。您可以这样做:

⟦1⟧ ∷ Four


那将是愚蠢的,没有人会使用这种愚蠢的语言,但这将是一种有效的语言。但是关键是指名语义使我们可以清楚地了解所编写程序的数学含义。这是使用lambda表示法对整数 x求平方的函数的表示法:

⟦square x⟧ ∷ λx → x²


现在我们可以继续讨论参照透明性。

参照透明与含义有关

请允许我再次to带乌代先生的回答。他写:


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


将其与您询问普通程序员参考透明性意味着什么时得到的答案进行比较。他们通常会说类似您在上面引用的答案:


引用透明性,是函数编程中常用的术语,表示给定功能和输入值,您将始终收到相同的输出。也就是说,函数中没有使用外部状态。


该答案根据值和副作用定义了引用透明性,但它完全忽略了含义。

这是在第二个定义下不是参照透明的函数:

var x = 0

func changeX() -> Int {
x += 1
return x
}


它读取一些外部状态,对其进行突变,然后返回该值。它不需要输入,每次调用时都返回一个不同的值,并且它依赖于外部状态。嗯大事了

给定正确的指称语义,它仍然是参照透明的。

为什么?因为您可以将其替换为另一个具有相同语义的表达式。

现在,该函数的语义更加混乱。我不知道如何定义它。它与状态转换有关,给定一个状态 s和一个产生新状态 s'的函数,该符号可能看起来像这样,尽管我不知道这在数学上是否正确:

⟦changeX⟧ ∷ λs → (s → s')


那正确吗?我没有头绪。 Strachey找出了命令式语言的指称语义,但它很复杂,我还不了解。然而,通过建立指示性语义,他确定了命令性语言与功能性语言一样具有参照透明性。为什么?因为数学含义可以精确描述。而且,一旦您知道某物的精确数学含义,就可以用具有相同含义的任何其他术语替换它。因此,即使我不知道 changeX函数的真正语义是什么,我也知道,如果我有另一个具有相同语义的术语,则可以将其中一个换成另一个。

那么 Date.now呢?

我对该功能一无所知。我什至不确定它来自什么语言,尽管我怀疑它可能是Java语言。但谁在乎。它的指称语义是什么?这是什么意思?您可以在不更改程序含义的情况下插入什么位置?

丑陋的事实是,我们大多数人都不知道!指称语义不是一开始就被广泛使用,命令式编程语言的指称语义确实很复杂(至少对我来说-如果您觉得很容易,我很乐意让您向我解释一下)。采取任何由超过20行非平凡代码组成的命令式程序,并告诉我其数学含义是什么。我挑战你。

相比之下,Haskell的指称语义非常简单。我对Haskell知之甚少。除了在ghci中搞乱之外,我从未在其中进行任何编码,但是使它如此强大的原因是,该语法比我所知道的任何其他语言都更紧密地跟踪语义。作为一种纯粹的严格功能语言,语义就在语法表面上。语法由定义含义的数学概念定义。

实际上,语法和语义紧密相关,以至于功能性程序员已经开始将两者混为一谈。 (我很谦虚地提出这一观点,并等待强烈的反对。)这就是为什么您从FP员工那里得到了引用透明性的定义,这些人谈论的是价值而不是意义。在像Haskell这样的语言中,两者几乎是无法区分的。由于没有可变状态,并且每个函数都是纯函数,因此您所要做的就是查看在评估函数并基本确定其含义时产生的值。

从某种意义上说,新时代FPer对参照透明性的解释也可能比我上面总结的有用。这是不容忽视的。毕竟,如果我上面写的是正确的,那么所有具有指称语义的事物都是参照透明的。没有所谓的非透明函数之类的东西,因为每个函数都有数学含义(尽管它可能晦涩难懂且难以定义),并且您始终可以用具有相同含义的另一个术语来代替它。那有什么好处?

好吧,这是有原因的。它让我们知道,我们对所从事的数学工作一无所知。就像我在上面说过的那样,我不知道 Date.now的指称语义是什么,或者从数学意义上讲它的含义是什么。它是参照透明的吗?是的,我确定是的,因为它可以被具有相同语义的另一个函数替换。但是我不知道如何评估该函数的语义,因此,作为程序员,其引用透明性对我没有用。

因此,如果我从这一切中学到的一件事,那就是将精力集中在某事是否符合“参照透明性”的定义上,而更多地放在尝试使程序从小巧,可数学组合的角度出发具有精确语义含义的部分,甚至我也能理解。

关于functional-programming - Date.now引用透明吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37244023/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com