我一直在考虑编程语言设计,并从Declarative Programming on Wikipedia:
的定义这与命令式编程形成对比,命令式编程需要对要运行的算法进行详细描述。
并进一步向下:
......任何非强制性的编程风格。 ...
然后继续表达功能语言,因为它们不是必要的,本质上是声明性的。
然而,这让我想知道,纯函数式编程语言是否能够解决任何算法问题,或者是基于该语言中可用函数的约束?
我最感兴趣的是关于这个主题的一般想法,虽然如果具体的例子可以说明这一点,我当然欢迎他们。
答案 0 :(得分:20)
答案 1 :(得分:13)
是的,Haskell,Erlang等是图灵完整的语言。原则上,您不需要可变状态来解决问题,因为您始终可以创建新对象而不是改变旧对象。当然,Brainfuck也是图灵完成的。换句话说,仅仅因为算法可以以函数式语言表达并不意味着它不是非常尴尬。
答案 2 :(得分:5)
好的,所以Church和Turing证明它是可能的,但我们如何做某事?
重写纯函数风格的命令式代码是我经常分配给本科生的一项练习:
有时出来的是混乱,但结果往往是出奇的优雅。唯一真正的诀窍是不传递永不改变的参数,而是将它们绑定在外部环境中。
答案 3 :(得分:1)
功能样式编程的最大区别在于它避免了可变状态。在命令式编程通常会更新变量的地方,函数式编程将定义新的只读值。
这会影响性能的主要地方是使用可更新数组的算法。命令式实现可以在O(1)时间内更新数组元素,而最好的纯函数式实现可以实现O(log N)(使用排序树)。
请注意,函数式语言通常有一些方法可以使用具有O(1)访问时间的可更新数组(例如,Haskell为其提供了状态转换器monad)。然而,这可以说是一种必要的编程方法......没有错;毕竟,你想为特定的工作使用最好的工具。
O(log N)增量数组更新的功能样式并非全是坏事,因为功能样式算法似乎很适合并行化。
答案 4 :(得分:1)
在@SteveB's answer上发布评论时间过长。
功能编程和命令式编程具有相同的功能:无论人们能做什么,另一个都能做到。他们被称为图灵完整。图灵机可以计算的函数正好递归函数理论和λ演算表达的函数。
但是,教会 - 图灵论文就是这样,无关紧要。它断言任何计算都可以由图灵机执行。这将非正式的想法 - 计算 - 与正式的想法 - 图灵机器联系起来。还没有人发现任何我们认为是图灵机无法做到的计算。将来有人会发现这样的事吗?谁能说出来。答案 5 :(得分:0)
使用状态monads,你可以在Haskell中以命令式编程。
因此,关于Haskell本质上是声明性的断言需要花费一些时间。从积极的方面来说,它等同于命令式编程语言,在实际意义上也不完全忽视效率。
答案 6 :(得分:0)
虽然我完全赞同援引Church-Turing论文的答案,但实际上这引出了一个有趣的问题。如果我有并行计算问题(在严格的数学意义上不是算法),例如多个生产者/消费者队列或几台机器之间的某些网络协议,这可以通过图灵机充分建模吗?它可以被模拟,但是如果我们模拟它,我们就失去了为什么我们在问题中具有并行性的目的(因为那时我们可以在图灵机上找到更简单的算法)。那么,如果我们不失去问题所固有的并行性(因此我们对它感兴趣的原因),我们就无法消除国家的概念呢?
答案 7 :(得分:0)
我记得在某个地方读过,当以纯粹的功能性方式解决时,有些问题变得更难,但我似乎无法找到参考。
如上所述,主要问题是阵列更新。虽然编译器可能在某些条件下使用可变数组,但必须保证在整个程序中只存在对该数组的一个引用。
这不仅是一个很难的数学事实,如果你不使用不纯的结构,它在实践中也是一个问题。
在一个更主观的说明中,声明所有图灵完整语言都是等价的,这只是在狭义的数学意义上。 Paul Graham在“The Blub Paradox”一节中探讨Beating the Averages中的问题。
图灵完整性等正式结果可能证明是正确的,但它们并不一定有用。 travelling salesman problem可能是NP完整的,但推销员却一直在旅行。似乎他们觉得不需要遵循“最优”路径,所以这个定理是无关紧要的。
注意:我并不是想尝试功能编程,因为我非常喜欢它。重要的是要记住它不是灵丹妙药。