Haskell和Python哪个是更具功能性的编程语言?

6

在学校的函数式编程课程中学习了Haskell。发现Haskell有点难以使用。现在已经大量使用Python,Python相当容易使用。

Python确实支持一些函数式编程结构。

正在考虑重新学习函数式编程。哪种语言更适合编码?Haskell还是Python?为什么?


4
没有更好的(功能性)编程语言,只有不同的语言。无论如何,Python 不是一个功能性编程语言。 - Chii
哦,别这样。对于这个问题打-1分是不公平的。如果你从未在Erlang、XSLT或Haskell中完成过项目,你可能会轻易地误解这些特性。 - Boldewyn
9
如果 Python 真的是一门函数式编程语言,这可能是主观的。实际上,Python 支持命令式风格和可变状态,并在需要时选择了几个函数式的构造方式。 - Ben James
1
如果你将“更好”编辑为“更具功能性”,它听起来就不那么主观了,而且可能会给他一个有用的答案。 - Ben James
1
好的...我并不想说哪种语言好或者不好,也不是说其中一种比另一种更好。只是想了解一下真正从事函数式编程的人对此的看法。如果这引发了争论,我很抱歉。 - Mayuresh
2
抱歉Mayuresh,大多数用户会在看到像“更好”的词语时产生一种条件反射般的反应,而没有真正考虑你的意图,因此会投票关闭。 - Ben James
6个回答

39
Haskell是一种函数式编程语言,而Python只具有某些函数式编程语言的特性。因此,问题得到解决。Q.e.d.
编辑:以递归函数调用的优化为例,Python缺乏的是这一点。这在大多数真正的函数式编程语言中非常重要。
顺便说一下,谷歌搜索刚刚产生了这篇不错的文章

33
你会在其他地方看到很多关于Python程序员不应该使用lambda等函数式特性的批评。Alex Martelli在这方面特别擅长。但是,如果你作为Python程序员来接近函数式编程,你将无法真正感受到人们对函数式编程感兴趣的原因。特别是,你将无法使用强大的静态类型系统和代数数据类型。这些工具绝对是Haskell思维方式的一部分。
函数式编程不仅仅是一组功能,而是一种思考方式。要看到这种思考方式并开始学习它,请查看John Hughes的论文Why Functional Programming Matters。你从Hughes那里学到的可以轻松应用于Haskell。实际上,Haskell更有可能迫使你学习这种新的思考方式。在Python中,你可以在这里使用一些lambda并欺骗自己正在学习函数式编程。但其实你并没有。
话虽如此,Haskell可能一次性包含了太多内容。如果你发现它很难理解,你可以尝试Standard MLRacket(前身为PLT Scheme或DrScheme)。Standard ML将向你介绍更多新的想法,但这些人并没有像Racketeers或Haskell人那样欢迎新手。

6
我认为一个强大的类型系统是一个主要优点。强大的宏系统也是一个主要优点,这就解释了LISP语言的一些流行之处。Erlang语言之所以受欢迎,不太是因为其函数式特性,而是因为其可靠性和可扩展的并行能力。此外,有一家主要的硬件制造商支持你当然是更好的。Ericsson对于电信和Erlang来说就像Sun对于计算机和Java一样,甚至可能更重要。 - Norman Ramsey
1
在 Haskell 中使用 QuickCheck(与 Erlang 相比)的简便性源自于其利用了 Haskell 的类型系统。因此,是的,Haskell 的类型系统对某些人来说可能会有所障碍(我认为类型类很复杂,会导致编写程序时不必要的困难),但它是强大的,并为 Haskell 实现的许多功能提供了基础。 - Charles Stewart
1
@Zak:类型系统肯定不是正交的。阅读Phil Wadler的论文《Theorems for Free》。Phil的结果与类型系统密切相关,仅在纯函数设置中才可能实现。至于相对重要性,这是一个合理的人们可以并且确实存在争议的话题,但大多数函数式程序员都重视类型。即使是Scheme也加入了这一行列:http://tinyurl.com/c6wgz6 - Norman Ramsey
@Norman Ramsey:感谢您提供这篇有趣论文的参考。我找到了一个非付费版本,但还没有机会阅读和消化它。也许我们使用术语的方式不同。我认为正交意味着特征之间不相互依赖,而不是拥有两者不会产生比其各自之和更大的整体。 - Zak
1
@Zak:我认为我们对正交的含义达成了一致。但是我想说的是,Haskell的类型系统与函数的纯度密切相关,在一个函数是一等公民但不纯的语言中,它会变得更加脆弱(或者甚至没有意义)。 - Norman Ramsey
显示剩余2条评论

11

这个问题凸显了我对函数式编程的常见理解之一的不满。拥有闭包和头等函数等语言特性并不会使语言成为一个“函数式编程语言”。函数式编程与特定的语言结构一样也是关于特定的编程“风格”。Python 有闭包、头等函数,甚至还有一个名叫“map”的函数,但是它本身鼓励过程化、面向对象、命令式编程风格; 所以即使您使用函数式特性,您仍然是在进行命令式编程。

作为一个“纯函数式语言”,Haskell 基本上要求人们采用声明式、函数式的编程风格,因此毋庸置疑,Haskell 比 Python 更“函数式”。


2
一流的函数需要适当的匿名lambda和合理的空间高效尾调用,而Python都没有。否则我完全同意。参见http://lambda-the-ultimate.org/node/3532#comment-50319。 - Charles Stewart

7
虽然Python确实支持一些函数式构造,但Haskell是一种函数式语言。你还需要考虑的是,Haskell也是纯函数式和惰性的,这两个概念可能是你在Haskell中遇到困难的原因。如果是这样的话,请继续阅读。
如果你有时间,可以考虑学习另一种较简单的函数式语言。我发现,在进入Haskell之前学习一种不那么"强制性函数式"的语言是值得一试的。你可以考虑OCaml(Objective Caml),另一种函数式编程语言,它既不是纯的也不是惰性的。因此,一些命令式编程结构将可供您使用(引用、循环、可变数组等),直到您真正需要处理monads为止。
这完全取决于你愿意花多少时间重温函数式编程,以及你当前在这个范例中的背景。

3
再说一遍,Haskell确实提供了可变数组、引用和循环。它们只是不是默认选项:IORef/ IOArray/ Control.Monad.for等。 - Don Stewart
同意,但它们是语言中相当晦涩的部分,通常不鼓励新用户使用甚至不会提到。 - CharlieP
3
@dons:这不是关于语言可以实现什么(请注意图灵漏洞),而是关于语言使得什么变得容易。 - Chuck

0

就像Boldewyn所说的那样。Haskell是最“强硬”的函数式语言之一,因为根本没有办法维护可变状态

话虽如此,Haskell与大多数人接触到的命令式和混合模型语言有着天壤之别,因此,如果一个人来自VB、C(++)或Java等背景,学习它需要一定的学习曲线。

另一方面,Python则具有“功能展示和演示”部分,在这个部分中,可以在主要是命令式环境下测试驱动几个功能性特征。

因此,如果在他最初的问题中,OP的“更好”意味着“更加功能性”或“更好的函数式编程语言”(正如他后来所表明的),那么Haskell毫无疑问是“赢家”。


1
Haskell 当然提供可变状态,只是它不是默认设置。请考虑基础库中的可变引用 (IORef/STRef) 和可变数组 (IOArray/STArray)。仅因为它不是默认设置,并不意味着它不存在。 - Don Stewart
7
当然,在Python中测试功能特性有点像启动汽车并将其停放在停车位上进行试驾。Guido本人对Python中的函数式编程相当挑剔。首先,lambda函数绝对是真正函数的二等公民。 - Chuck

-3

来自Haskell主页

Haskell是一种高级纯函数式编程语言。它是二十多年前尖端研究的开源产品,允许快速开发强大,简洁,正确的软件。

调侃翻译:

  • "高级" = "不适合所有人"
  • "纯函数式" = "绝对不适合所有人"
  • "二十多年" = "仍然不是每个人都喜欢!"
  • "尖端研究" = "有可能你会发现一个实际问题,可以用它来解决,但我们还在努力!"
  • "强大,简洁,正确的软件" = "你是否缺少简单,易懂,显而易见,可读性强的东西?猜猜为什么呢!"

开玩笑了,函数式语言并不适合大多数人,永远也不会适合。虽然有些人能像栈一样思考,但我更希望计算机更加努力地理解我的胡言乱语。


6
栈与函数式语言有什么关系?如果你喜欢使用栈,Forth是一种可以选择的语言。但如果你认为栈是对函数式语言的评价基础,我怕你需要经过漫长、艰难的学习之路才能真正理解它们。这话里面还带点讽刺成分。 - rvirding
9
你的主张是函数式编程与底层太相近?在C语言占主导地位的世界中,更不可能了吧?你一定是服药过量了。Haskell是非常高级的。你实际上想表达的是,“这不是我已经了解的”。 - Chuck
17
@Aaron:你说你“更希望计算机尽力理解你的胡言乱语。” Haskell 比大多数流行的编程语言更让计算机为你进行思考。认为 C “更努力地理解你的胡言乱语” 看起来很奇怪。我也不认为需要在我的脑海中模拟堆栈才能编写递归解决方案。我是你能找到的最愚蠢的程序员之一,但我也能够理解它。即使明确递归是必要的(这比人们想象中更少见),你通常只需要编写一个转换和它应该终止的条件。 - Chuck
12
稍微解释一下:使用迭代解决方案更容易写出微妙且令人讨厌的差一错误(我昨天在这里看到一个问题,结果证明是差一错误——经过很多调试)。Haskell中的等效代码可能是map (* 2) list。我不需要在脑海中构想堆栈,也没有任何错误的空间。我只需告诉它,“我想把所有这些东西加倍”,然后它就为我完成了。 - Chuck
8
@Carl: 我们和rvirding意见不同的是,“撇开玩笑不谈”的部分。开头的幽默其实挺有趣的(除了他好像不知道“简明”是指“简单,易懂,显而易见,可读性强”这一部分)。 - Chuck
显示剩余9条评论

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