我必须承认我对函数式编程了解不多。我从这里和那里读到它,所以开始知道在函数式编程中,一个函数返回相同的输出,对于相同的输入,无论函数被调用多少次。它就像一个数学函数,对于函数表达式中包含的输入参数的相同值,计算出相同的输出。

例如,考虑这个:

f(x,y) = x*x + y; // It is a mathematical function

不管你用了多少次f(10,4)它的值总是104。因此,无论你在哪里写f(10,4),你都可以用104替换它,而不改变整个表达式的值。此属性称为表达式的引用透明性。

正如维基百科所说,

相反,在函数式代码中,函数的输出值只取决于函数的输入参数,因此调用函数f两次,参数x的值相同,两次将产生相同的结果f(x)。

函数式编程中是否存在时间函数(返回当前时间)?

如果是,那它怎么可能存在?它是否违反了函数式编程的原则?它尤其违反了引用透明性,这是函数式编程的特性之一(如果我理解正确的话)。 如果没有,那么在函数式编程中如何知道当前时间呢?


当前回答

大多数函数式编程语言都不是纯粹的,也就是说,它们允许函数不仅依赖于它们的值。在这些语言中,完全有可能有一个返回当前时间的函数。从你标记这个问题的语言中,这适用于Scala和f#(以及ML的大多数其他变体)。

在Haskell和Clean等纯语言中,情况就不同了。在Haskell中,当前时间不是通过函数,而是通过所谓的IO操作,这是Haskell封装副作用的方式。

在Clean中,它将是一个函数,但该函数将以一个世界值作为参数,并返回一个新的世界值(除了当前时间)作为结果。类型系统将确保每个世界值只能使用一次(并且每个消耗世界值的函数将产生一个新的世界值)。这样,每次调用time函数时都必须使用不同的参数,因此允许每次返回不同的时间。

其他回答

是的,函数式编程中可以存在一个获得时间的函数,它使用了函数式编程的一个稍微修改过的版本,称为非纯函数式编程(默认的或主要的是纯函数式编程)。

在获取时间(或读取文件,或发射导弹)的情况下,代码需要与外部世界进行交互以完成工作,而这个外部世界并不是基于函数式编程的纯粹基础。为了允许纯函数式编程世界与这个不纯的外部世界进行交互,人们引入了不纯函数式编程。毕竟,不与外部世界交互的软件除了做一些数学计算之外没有任何用处。

很少有函数式编程语言具有这种内嵌的不纯特性,这样就不容易区分哪些代码是不纯的,哪些是纯的(如f#等),而一些函数式编程语言确保当你做一些不纯的事情时,代码与纯代码相比明显突出,如Haskell。

另一种有趣的方式是,函数式编程中的get time函数将接受一个“world”对象,该对象具有世界的当前状态,如时间、生活在世界中的人数等。然后从世界对象中获取时间,这个世界对象总是纯的,即你在相同的世界状态下通过,你将总是得到相同的时间。

我很惊讶,没有一个答案或评论提到共代数或共归纳。通常,同归纳法在对无限数据结构进行推理时被提及,但它也适用于无穷无尽的观察流,例如CPU上的时间寄存器。一个协代数模型隐藏状态;同感应模型观察到这种状态。(正常诱导模型构造状态。)

这是响应式函数式编程中的一个热门话题。如果你对这类东西感兴趣,请阅读以下内容:http://digitalcommons.ohsu.edu/csetech/91/(28页)

Richard B. Kieburtz,“响应式函数式编程”(1997)。CSETech。第91篇(链接)

大多数函数式编程语言都不是纯粹的,也就是说,它们允许函数不仅依赖于它们的值。在这些语言中,完全有可能有一个返回当前时间的函数。从你标记这个问题的语言中,这适用于Scala和f#(以及ML的大多数其他变体)。

在Haskell和Clean等纯语言中,情况就不同了。在Haskell中,当前时间不是通过函数,而是通过所谓的IO操作,这是Haskell封装副作用的方式。

在Clean中,它将是一个函数,但该函数将以一个世界值作为参数,并返回一个新的世界值(除了当前时间)作为结果。类型系统将确保每个世界值只能使用一次(并且每个消耗世界值的函数将产生一个新的世界值)。这样,每次调用time函数时都必须使用不同的参数,因此允许每次返回不同的时间。

是也不是。

不同的函数式编程语言解决这些问题的方法不同。

在Haskell(一个非常纯粹的Haskell)中,所有这些东西都必须发生在一个叫做I/O单子的东西中——看这里。

你可以把它看作是将另一个输入(和输出)输入到你的函数(世界状态)中,或者更简单地认为是“不确定性”发生的地方,比如得到变化的时间。

像f#这样的其他语言只是内置了一些不纯性,所以你可以有一个函数为相同的输入返回不同的值——就像普通的命令式语言一样。

正如杰弗里·伯卡在他的评论中提到的: 下面是来自Haskell wiki的I/O单子的介绍。

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