Haskell 函数式编程中切换顺序后输出一致性的保证

Haskell 函数式编程中切换顺序后输出一致性的保证,haskell,functional-programming,Haskell,Functional Programming,我开始阅读Haskell的一些文档,其中有一个基本概念我不明白。我在其他地方也读过,但我想一劳永逸地理解它 在许多讨论函数编程的地方,我一直在读到,如果您使用的函数是纯函数(没有副作用,并且每次调用时对相同的输入给出相同的响应),那么您可以在编写它们时切换调用它们的顺序,保证此组合调用的输出无论顺序如何都保持不变 例如,这里是: Haskell是一种纯语言,这意味着任何 函数调用完全由其参数决定。伪函数 与C中的rand()或getchar()类似,它们在每个 电话,是根本不可能写在哈斯克尔。此

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

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

例如,这里是:

Haskell是一种纯语言,这意味着任何 函数调用完全由其参数决定。伪函数 与C中的rand()或getchar()类似,它们在每个 电话,是根本不可能写在哈斯克尔。此外,哈斯克尔 函数不会有副作用,也就是说它们不会产生副作用 对“真实世界”的任何更改,如更改文件、写入 屏幕显示、打印、通过网络发送数据等。这两个 限制加在一起意味着任何函数调用都可以替换为 具有相同参数的上一次调用的结果,以及 语言保证所有这些重新安排不会改变 节目结果

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

x(a)->a+3
y(a)->a*3
z(a)->x(y(a))
w(a)->y(x(a))
现在,如果我们执行
z
w
,我们得到:

z(5)//给出3*5+3=18
w(5)//给出(5+3)*3=24
既然如此,我想我误解了他们所说的承诺。有人能给我解释一下吗?

当你将
x(y(a))
y(x(a))
进行比较时,这两个表达式是不等价的,因为
x
y
不是用相同的参数调用的。在第一个表达式中,
x
用参数
y(a)
调用,
y
用参数
a
调用。而在第二个
y
调用时使用
x(a)
,而不是
a
,作为其参数,
x
调用时使用
a
,而不是
y(a)
。所以:不同的论点,(可能)不同的结果

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

a = f(x)
b = g(y)
a = getchar()
b = getchar()
您可以在不影响其值的情况下切换
a
b
的定义。也就是说,无论是在
g
之前调用
f
,还是在
g
之前调用
f
都没有区别。以下代码显然不是这样:

a = f(x)
b = g(y)
a = getchar()
b = getchar()

如果在这里切换
a
b
,它们的值也会切换,因为
getchar
每次调用时都返回一个(可能)不同的字符。因此,一种纯函数式语言不能有一个完全像
getchar

那样的函数。谢谢,我想我只是把它们的保证发挥到了极致:)