为什么要选择纯函数式语言而不是“不纯”的函数式语言?

5
如果一个非理论计算机科学家想要学习一门纯函数式编程语言,比如Haskell或Erlang,而不是一门带有强烈函数式组成部分的“杂交”语言,比如Python或D2,那么它的优势在哪里呢?我的观点如下:
  1. 没有一种范式是完美的。无论使用什么范式的单一范式语言都具有很强的限制性。
  2. Python或D2可以帮助你在完成实际工作的同时逐步了解函数式编程。而Haskell或Erlang则会迫使你在能够做任何有趣的事情之前一次性地学习函数式风格。

编辑:通过“杂交”函数式语言,我真正意思是带有函数式特色的强大多范式语言,而不是带有一些非函数式能力的强大函数式语言。


1
嗯,我想OCaml或Scheme可以作为不纯的函数式编程语言的例子。我并不了解D语言,但Python与λ演算远离得很远。 - Chuck
11
Python并不是非常适合函数式编程。当你使用Python时,不要被骗认为你正在进入函数式编程的领域。如果你想选择一个能够真正掌握命令式和函数式编程的语言,我建议使用Scala。 - Ben James
2
一个函数式语言并不仅仅是具有一级函数的任何语言。 - Jimmy
5个回答

12

一切取决于你想要实现什么目标。如果你的目标是在一个函数式语言中编写生产代码,那么“纯”函数式语言可能会使其更加困难。

但是,如果你试图学习新的概念,“纯”语言会让你受益,因为它可以帮助你避免滑向非函数式概念的方向。一旦你清楚了这些差异,就可以去尝试混合环境,比如F#,但在此之前,很容易陷入面向对象的做事方式,错过函数式方法的优势。

在其他主题中,我提出了一个观点,认为学习F#的更好方法是从Haskell开始(这个观点被投票否决),但如果你学习F#是为了面向对象编程,那么学习F#还有什么意义呢?还不如留在C#中。


1
我认为这是一个很好的观点。我开始研究F#,但我的面向对象编程训练成了阻碍。现在我想先研究一下Haskel。 - Jason
如果你的目标是在函数式语言中编写生产代码,那么“纯”函数式语言可能会使它更加困难 - 为什么? - Ivan Perez

11

你已经接近回答自己的问题:

Haskell 或 Erlang 将会在你能够进行任何有趣的东西之前强制让你一次性学习函数式编程风格。

实际上,根据你所说的“有趣”,你可以在一周内就能够以 Haskell 提高生产力。

所有人学习 Haskell 的主要原因(语言理论家已经掌握它,其他类型的理论家忙于证明定理而不受编程困扰)是学习 Haskell 将改变你思考编程的方式。特别是类型系统、列表推导(被 Python 借鉴——最高的赞誉),以及使用模式匹配进行编程。你将能够在所有编程中使用许多新的想法。并且 Haskell 将强制你以其他语言无法做到的方式思考新的想法。

Erlang 是一种值得尊敬的语言,但是没有类似 Haskell 的类型系统。


如果你喜欢 Paul Graham,你可以阅读他的文章《打败平均数》,特别是关于“Blub 悖论”的部分。只需将 Lisp 替换为 Haskell :-)


6
您学习的收获不多,如果您的“新”语言只是您已经了解的知识的微小变化。这就好比问:“我为什么要学中文,当我可以找一个方言教练来教我说苏格兰口音?”我想如果您喜欢讲方言,那没问题,但您并没有真正扩展自己的专业知识。
学习一门函数式语言可以让您学会一种全新的思考方式。像OCaml这样的不纯或混合范例语言也很好,但使用不纯元素来避免用一种新的方式思考问题可能会很诱人。函数式语言并不是万能钥匙,但它们确实有很多有趣的好处,如果您学习一种具有“函数组件”的语言但它并不像真正的函数式语言一样工作,那么您就会失去这些好处。
例如,在像Haskell这样的纯函数式语言中,状态被非常谨慎地与程序的其余部分隔离开来。这使得在其他语言中非常困难的优化变得微不足道。例如,状态是并行处理的敌人。在Haskell中,您可以看一个函数的类型并且100%确定它不会创建任何副作用。
这种以函数为中心的思考方式,以及使用不可变数据结构的方法是一种纯函数式语言可以教给您的技能。我并不是说纯函数式语言是“最好的”,但它们有自己的好处。这是您工具箱中的另一个工具。如果您坚持使用已经熟悉的内容,您就无法获得该工具。

2
Erlang是纯函数式的吗?老实说,我认为它不是。
我不是专家,所以请谨慎对待我的话。
副作用会防止(或使得)许多优化变得更加复杂,包括并行处理。因此,理论上来说,纯函数式编程应该意味着更好的优化和更快的代码,尽管我不确定这在实践中是否成立。即使没有,也可能有一天会出现一个纯函数式语言,使使用所有核心变得轻而易举。
此外,从某种意义上说,没有副作用的编程可以使程序更容易理解。

Erlang的整个存在理由就是并行处理。它真的很容易使用你拥有的所有核心。数据并行Haskell虽然还很新,但也非常令人印象深刻。Supero Haskell是另一个例子,展示了Haskell强类型、纯函数式特性所能实现的疯狂优化。 - Chuck
1
说到对程序进行推理,如果按照过程化的方式编写函数体更容易一些,但不能允许在函数体外可见的副作用,这样做有什么问题吗? - dsimcha
Chuck Erlang的整个存在的理由是分布式编程,而不是使用多个核心进行并行处理。最后一次我检查Erlang并不支持多核心(除非你为每个核心启动一个虚拟机)。可能自2007年以来有所改变。 - Daniel O

1

因为仅有纯粹的声明式在操作语义层面上。纯函数式编程(即消除意外依赖)是并行所必需的

此外,如果没有不可变性限制,你就不会被迫思考如何以与命令式编程一样快的速度执行算法,或者如何使用函数响应式编程模拟与现实世界的交互而不会出现状态混乱。

因此,你将无法最大化你编写最大程度可组合和可扩展代码的技能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接