“纯粹”在“纯函数式语言”中意味着什么?

时间:2010-12-07 22:17:56

标签: haskell functional-programming

Haskell被称为“纯函数式语言”。

在这种情况下,“纯粹”意味着什么?这对程序员有什么影响?

7 个答案:

答案 0 :(得分:57)

功能语言中,您不能做任何有副作用的事情。

副作用意味着评估表达式会改变某种内部状态,这种状态稍后会导致评估同一表达式产生不同的结果。在纯函数式语言中,您可以根据需要使用相同的参数来计算相同的表达式,并且它总是返回相同的值,因为没有要更改的状态。

例如,纯函数式语言不能有赋值运算符或输入/输出,尽管实际上,即使是纯函数式语言也经常调用不纯的库来进行I / O.

答案 1 :(得分:32)

“纯粹”和“功能性”是两个独立的概念,尽管没有另一个概念不是很有用。

纯表达式是幂等的:它可以被计算任意次数,每次都有相同的结果。这意味着表达式不能有任何可观察到的副作用。例如,如果一个函数改变了它的参数,在某个地方设置了一个变量,或者根据其输入之外的其他东西改变了行为,那么该函数调用就不是纯粹的了。

函数式编程语言是函数是一流的语言。换句话说,您可以使用与操作所有其他第一类值完全相同的方便来操作函数。例如,能够使用“函数返回bool”作为“表示集合的数据结构”在函数式编程语言中很容易。

函数式编程语言中的编程通常以大多数纯粹的方式进行,如果没有函数式编程语言启用的高阶函数操作,很难完全纯粹。

Haskell是一种函数式编程语言,其中(几乎)所有表达式都是纯粹的;因此,Haskell是一种纯函数式编程语言。

答案 2 :(得分:23)

纯函数是没有副作用的函数 - 它接受一个值并返回一个值。功能修改没有全局状态。纯函数语言是强制函数纯粹的语言。纯度有许多有趣的结果,例如评估可能是惰性的 - 因为函数调用没有任何目的而是返回一个值,那么如果你不打算使用它就不需要实际执行该函数它的价值。由于这一点,Haskell中常见的无限列表上的递归函数。

另一个结果是,评估函数的顺序无关紧要 - 因为它们不会相互影响,您可以按任何方便的顺序执行它们。这意味着并行编程带来的一些问题根本不存在,因为执行函数没有“错误”或“正确”的顺序。

答案 3 :(得分:11)

严格地说,函数语言是一种函数式语言(即函数是第一类值的语言),其中表达式没有副作用。术语“纯功能语言”是同义词。

根据这个定义,Haskell不是一种纯函数式语言。您可以编写显示结果,读取和写入文件,具有GUI等的程序的任何语言都不是纯粹的功能。因此,没有通用的编程语言是纯函数式的(但是有一些有用的特定于域的纯函数式语言:它们通常可以某种方式被视为嵌入式语言)。

有一种有用的放松感觉,像Haskell和Erlang这样的语言可以被认为是纯粹的功能,但ML和Scheme之类的语言却不能。如果有一个相当大的,有用的和充分表征的子集,其中副作用是不可能的,那么语言就可以被认为是纯粹的功能。例如,在Haskell中,所有类型不是由IO或其他效果表示monad构建的程序都是无副作用的。在Erlang中,所有不使用IO诱导库或并发功能的程序都是无副作用的(这比Haskell案例更具延伸性)。相反,在ML或Scheme中,副作用可以隐藏在任何函数中。

从这个角度来看,Haskell的纯功能子集可以看作是处理每个monad内部行为的嵌入式语言(当然这是一个奇怪的视角,因为几乎所有的计算都发生在这个“嵌入式”子集中),Erlang的纯功能子集可以看作嵌入式语言处理本地行为。


Graham Huttonpurely functional languages主题略有不同且非常有趣的观点:

  

有时,术语“纯功能”在更广泛的意义上也用于表示可能包含计算效果的语言,但不改变“功能”的概念(由功能的基本属性保留的事实证明)通常,表达式的评估可以产生“任务”,然后单独执行该任务以产生计算效果。评估和执行阶段以评估阶段不会损害表达式和函数的标准属性的方式分开。例如,Haskell的输入/输出机制就是这种。

即。在Haskell中,函数具有类型a -> b并且不具有副作用。类型IO (a -> b)的表达式可能有副作用,但它不是函数。因此在Haskell函数中必须是纯函数,因此Haskell是纯函数式的。

答案 4 :(得分:4)

由于纯功能代码不会产生任何副作用,因此无需检查或验证外部状态即可轻松进行测试。此外,正因为如此,扩展代码可能会变得更容易。

在扩展/修复(或尝试修复)代码时,我没有计算出遇到非明显副作用的次数。

答案 5 :(得分:4)

正如其他人所提到的,“纯函数式编程语言”中的“纯”一词指的是缺乏可观察到的副作用。对我来说,这直接引出了一个问题:

什么是副作用?

我已经看到副作用被解释为

  • 除了简单地计算结果之外,函数所做的事情
  • 可能影响除函数输入之外的函数结果的东西。

如果第一个定义是正确的,那么任何执行I / O的函数(例如写入文件)都不能说是“纯”函数。虽然Haskell程序可以调用导致I / O执行的函数,但根据这个定义,Haskell似乎不是纯函数式编程语言(正如它声称的那样)。

由于这个原因和其他原因,我认为第二个定义是更有用的定义。根据第二个定义,Haskell仍然可以声称是一个完全纯粹的函数式编程语言,因为只使用函数输入才能使I / O执行计算结果。我认为,Haskell如何调和这些看似矛盾的要求是非常有趣的,但我会抵制在回答实际问题时偏离任何进一步的诱惑。

答案 6 :(得分:2)

Amr Sabry写了一篇关于纯函数式语言的paper。如果我们忽略像unsafePerformIO这样的东西,Haskell就被认为是纯粹的。使用这个定义也使ML和Erlang不纯。大多数语言的子集都符合纯粹的条件,但我个人认为将C语言作为纯语言并不是非常有用。

高阶与纯度正交,你可以设计一个纯粹的一阶函数语言。