“纯”在“纯function语言”中意味着什么?
Haskell被称为“纯function语言”。
在这方面“纯”是什么意思? 这对程序员有什么影响?
在纯粹的function语言中,你不能做任何有副作用的事情。
副作用将意味着评估一个expression式会改变一些内部状态,以后会导致评估相同的expression式有不同的结果。 在纯粹的函数式语言中,您可以使用相同的参数来评估相同的expression式,因为它们不会改变状态。
例如,一个纯粹的函数式语言不能有一个赋值运算符或input/输出,尽pipe为了实际的目的,即使是纯粹的函数式语言也会经常调用不纯粹的库来执行I / O操作。
“纯粹”和“function”是两个单独的概念,但没有其他概念是没有用的。
一个纯粹的expression是幂等的:它可以被评估多次,每次都有相同的结果。 这意味着expression式不能有任何可观察到的副作用。 例如,如果一个函数突变了它的参数,在某个地方设置了一个variables,或者根据除了它的input之外的东西改变了行为,那么这个函数调用就不是纯粹的。
function编程语言是function一stream的编程语言。 换句话说,您可以使用完全一样的方便操作函数来操作所有其他一stream的值。 例如,能够使用“返回布尔函数”作为“表示集合的数据结构”在function性编程语言中将是容易的。
函数式编程语言中的编程通常是以大体上纯粹的风格完成的,如果没有函数式编程语言支持的高阶函数操作,就很难完全纯粹。
Haskell是一种函数式编程语言,其中(几乎)所有expression式都是纯粹的; 因此,Haskell是一个纯粹的函数式编程语言。
一个纯粹的function是一个没有副作用的function – 它需要一个价值和价值。 没有function修改的全局状态。 纯粹的function语言是强制function是纯粹的function语言。 纯度有一些有趣的结果,例如评估可能是懒惰的事实 – 因为函数调用没有目的,只能返回一个值,所以如果你不打算使用,你不需要实际执行函数它的价值。 由于这个原因,无限列表上的recursion函数在Haskell中很常见。
另一个结果是,评估函数的顺序并不重要,因为它们不能互相影响,所以你可以按照任何顺序进行操作。 这意味着并行编程带来的一些问题根本就不存在,因为函数没有执行“错误”或“正确”的顺序。
严格地说, 纯粹的function语言是一种function语言(即function是一等价值的语言),在这种语言中,expression式没有副作用。 术语“纯function语言”是同义词。
通过这个定义,Haskell不是一个纯粹的function语言。 任何可以编写显示结果的程序,读写文件,具有GUI等等的语言都不是纯粹的function。 因此,没有通用的编程语言是纯粹的function(但是有一些有用的领域特定的纯function语言:它们通常可以被看作是某种方式的embedded式语言)。
像Haskell和Erlang这样的语言可以被认为是纯粹的function,但是ML和Scheme这样的语言却不能。 一种语言可以被认为是纯粹的function,如果有一个相当大的,有用的和很好的特征子集,副作用是不可能的。 例如,在Haskell中,所有types不是由IO
或其他效果表示monad构build的程序都是无副作用的。 在Erlang中,所有不使用IO诱导库或并发function的程序都是无副作用的(这比Haskell案例更加深入)。 相反,在ML或Scheme中,副作用可以埋在任何函数中。
从这个angular度来看,Haskell的纯粹function子集可以被看作是处理每个monad内部行为的embedded式语言(当然这是一个奇怪的观点,因为几乎所有的计算都是在这个“embedded”子集中发生的) Erlang的纯function子集可以看作是embedded式语言处理本地行为。
格雷厄姆·赫顿(Graham Hutton)对纯粹function性语言的观点略有不同,而且颇为有趣。
有时候,“纯粹function”这个术语在更广泛的意义上也被用来表示可能包含计算效果的语言,但是并没有改变“function”的概念(正如事实certificate,function的基本属性被保留了下来)。 ,expression式的评估可以产生一个“任务”,然后单独执行这个任务来产生计算效果。 评估和执行阶段是这样分开的,评估阶段不损害expression式和函数的标准属性。 例如,Haskell的input/输出机制就属于这种types。
也就是说,在Haskell中,函数的typesa -> b
,不能有副作用。 typesIO (a -> b)
的expression可能有副作用,但它不是函数。 因此,在Haskell函数中必须是纯粹的,因此Haskell是纯粹的function。
由于在纯函数代码中不会有任何副作用,因为没有外部状态来检查或validation,所以testing变得更容易。 而且,因此,扩展代码可能变得更容易。
在扩展/修复(或试图修复)代码时,我忽略了非显而易见的副作用的次数。
正如其他人所提到的,“纯函数式编程语言”中的“纯”一词是指缺乏可观察的副作用。 对我而言,这直接导致了这样一个问题:
什么是副作用?
我已经看到副作用解释为
- 除了简单地计算其结果以外,函数的作用
- 这可能会影响function的input以外的function的结果。
如果第一个定义是正确的,那么任何执行I / O(例如写入文件)的函数都不能说是“纯”函数。 而Haskell程序可以调用导致I / O执行的函数,Haskell似乎并不是纯粹的函数式编程语言(据称是),根据这个定义。
由于这个和其他原因,我认为第二个定义是更有用的。 根据第二个定义,Haskell仍然可以声称是一个完全纯粹的函数式编程语言,因为导致I / O执行的函数只根据函数input计算结果。 Haskell如何调和这些看似相互冲突的要求是相当有趣的,但是我想抵制这个诱惑,不能回答真正的问题。
Amr Sabry写了一篇关于纯粹的function语言的文章。 如果我们忽略像unsafePerformIO这样的事情,Haskell就被认为是纯粹的。 使用这个定义也使ML和Erlang不纯。 大多数语言的子集合都是纯粹的,但是我个人认为谈论C是纯粹的语言并不是很有用。
高阶与纯度正交,可以devise一个纯粹的一阶泛函。