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

例如,考虑这个:

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

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

正如维基百科所说,

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

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

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


当前回答

如果是,那它怎么可能存在?这难道不违反原则吗 函数式编程吗?它尤其违反了参照原则 透明度

它的存在不是纯粹的功能性的。

如果不是,那么如何知道当前时间是泛函的 编程吗?

首先,了解如何在计算机上检索时间可能是有用的。从本质上讲,有一个板载电路来记录时间(这就是电脑通常需要一个小电池的原因)。然后可能会有一些内部进程在某个内存寄存器上设置时间的值。这本质上可以归结为CPU可以检索到的值。


对于Haskell,有一个“IO动作”的概念,它表示一种类型,可以执行一些IO进程。因此,我们不引用时间值,而是引用IO时间值。所有这些都是纯功能性的。我们引用的不是时间,而是“读取时间寄存器的值”之类的东西。

当我们实际执行Haskell程序时,IO操作将实际发生。

其他回答

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

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

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

“当前时间”不是一个函数。它是一个参数。如果您的代码依赖于当前时间,这意味着您的代码是由时间参数化的。

如果是,那它怎么可能存在?这难道不违反原则吗 函数式编程吗?它尤其违反了参照原则 透明度

它的存在不是纯粹的功能性的。

如果不是,那么如何知道当前时间是泛函的 编程吗?

首先,了解如何在计算机上检索时间可能是有用的。从本质上讲,有一个板载电路来记录时间(这就是电脑通常需要一个小电池的原因)。然后可能会有一些内部进程在某个内存寄存器上设置时间的值。这本质上可以归结为CPU可以检索到的值。


对于Haskell,有一个“IO动作”的概念,它表示一种类型,可以执行一些IO进程。因此,我们不引用时间值,而是引用IO时间值。所有这些都是纯功能性的。我们引用的不是时间,而是“读取时间寄存器的值”之类的东西。

当我们实际执行Haskell程序时,IO操作将实际发生。

在函数式编程中时间函数是如何存在的?

早在1988年,Dave Harrison在定义带有实时处理功能的早期函数式语言时就面临着这个问题。他为Ruth选择的解决方案可以在他的论文《功能性实时编程:Ruth语言及其语义》第50页中找到:

一个唯一的时钟在运行时自动提供给每个Ruth进程,以提供实时信息,[…]

那么这些时钟是如何定义的呢?第61页:

时钟树由一个表示当前时间的非负整数节点和两个包含未来事件时间的子树组成。

此外:

当树被(惰性地)计算时,每个节点都被实例化为节点实例化时的系统时间值,从而使程序引用当前时间。

翻译成Haskell:

type Clock = Tree Time
type Time  = Integer -- must be zero or larger

data Tree a = Node { contents :: a,
                     left     :: Tree a,
                     right    :: Tree a }

除了访问当前时间(带内容)之外,每个Ruth进程还可以提供其他时钟(带左时钟和右时钟),以便在程序的其他地方使用。如果一个进程不止一次需要当前时间,那么它必须每次都使用一个新节点——实例化后,节点的内容保持不变。

这就是函数式语言中时间函数的存在方式:无论调用它的地方,它总是应用于唯一的输入值(在这里是一个时间树)。

不引入计划生育的其他概念就可以回答这个问题。

可能性1:time作为函数参数

一门语言包括

语言核心和 标准库。

引用透明性是语言核心的属性,而不是标准库的属性。它绝不是用那种语言编写的程序的属性。

使用OP的符号,应该有一个函数

f(t) = t*v0 + x0; // mathematical function that knows current time

他们会要求标准库获取当前时间,比如1.23,并以该值作为参数f(1.23)(或者只是1.23*v0 + x0,参考透明!)来计算函数。这样代码就能知道当前时间。

可能性2:返回值为时间

回答OP的问题:

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

是的,但是这个函数必须有一个参数,你必须用不同的输入来计算它,这样它就会返回不同的当前时间,否则它就违反了FP的原则。

f(s) = t(s)*v0 + x0; // mathematical function t(s) returns current time

这是我上面所描述的另一种方法。但话又说回来,首先获取这些不同输入的问题仍然归结为标准库。

可能性3:函数式响应式编程

其思想是函数t()计算为与函数t2配对的当前时间。当需要当前时间时,调用t2(),它会给函数t3,以此类推

(x, t2) = t(); // it's x o'clock now
...
(x2, t3) = t2(); // now it's already x2 o'clock
...
t(); x; // both evaluate to the initial time, referential transparency!

关于FP还有更多,但我认为这超出了op的范围。例如,如何要求标准库计算一个函数,并以纯函数的方式对其返回值进行操作:这是关于副作用而不是参考透明度的。