在函数式编程中切换顺序后保证输出的相同性

Tal*_*Tal 0 haskell functional-programming

我开始阅读一些Haskell的文档,并且有一个我根本不理解的基本概念.我也在其他地方读过它,但我想一劳永逸地理解它.

在许多讨论功能编程的地方,我一直在阅读如果您使用的功能是纯粹的(没有副作用,并且在每次调用时对相同的输入给出相同的响应)那么您可以切换它们被调用时的顺序.组成它们,保证无论顺序如何,这个组合调用的输出都将保持不变.

例如,这是来自Haskell Wiki的条目:

Haskell是一种纯语言,这意味着任何函数调用的结果完全由其参数决定.像C中的rand()或getchar()这样的伪函数在每次调用时都会返回不同的结果,这些函数根本不可能在Haskell中编写.而且,Haskell函数不能有副作用,这意味着它们不能对"真实世界"进行任何更改,例如更改文件,写入屏幕,打印,通过网络发送数据等.这两个限制一起意味着任何函数调用都可以被具有相同参数的先前调用的结果替换,并且语言保证所有这些重新排列不会改变程序结果!

但是当我摆弄这个想法时,我可以很快想到与上述陈述相矛盾的例子.例如,假设我有两个函数(我将使用伪代码而不是Haskell):

x(a)->a+3

y(a)->a*3


z(a)->x(y(a))

w(a)->y(x(a))
Run Code Online (Sandbox Code Playgroud)

现在,如果我们执行zw,我们得到:

z(5) //gives 3*5+3=18

w(5) //gives (5+3)*3=24
Run Code Online (Sandbox Code Playgroud)

既然如此,我想我误解了他们所说的承诺保证.任何人都可以向我解释一下吗?

sep*_*p2k 8

当你比较x(y(a))y(x(a)),这两个表达式不是等价的,因为xy没有在每个表达式中调用相同的参数.在第一个表达式x被称为使用参数y(a)y被调用的自变量a.而在第二个y被称为x(a),而不是a,作为其论点,x并被称为a,而不是y(a).所以:不同的论点,(可能)不同的结果.

当人们说订单无关紧要时,他们的意思是在以下代码中:

a = f(x)
b = g(y)
Run Code Online (Sandbox Code Playgroud)

您可以切换定义,a也可以b不影响其值.也就是说,f之前是否被调用没有区别,g反之亦然.以下代码显然不是这样:

a = getchar()
b = getchar()
Run Code Online (Sandbox Code Playgroud)

如果您切换ab位置,它们的值转换为好,因为getchar回报率(可能)不同的每一个它被称为实时性.因此,纯功能语言不能具有完全相同的功能getchar.