为什么不依赖于更改状态有什么好处?


16

这个问题出自问题/software/25569/is-haskell-worth-learning

通常,对于Haskell如何提高您在其他语言中的编码技能,通常会重复声明一些,此外,这是因为Haskell是无状态的,这是一件好事。

为什么?

我见过有人将其与只用左手打字,或者闭上眼睛一天,仅依靠触摸来进行比较。当然,还有更多呢?

它与硬件内存访问有关,还是与其他性能提升有关?


2
Haskell是学者。我会看里奇·希基(Richard Hickey)关于克洛瑞(Clojure)的一些演讲-在那儿他提出了杀手级的务实论点(类似于哈维尔(Javier)的3分,但也很简单)。
乔布斯


6
仅仅因为Haskell是“学术的”,并不意味着它是不切实际的或不务实的。
迪洪

Answers:


17

我的头上至少有三大优势:

  1. 它使程序更接近数学表达式。在数学中,x它不变,直到解决方程式,您才知道它是什么。

  2. 最后,还有状态改变(毕竟,这是计算机如何工作在较低水平); 但仅限于特定语言。因为编译器知道它不会改变其他代码所依赖的任何内容,所以它为编译器提供了移动代码进行优化的巨大机会。

  3. 并发代码无需同步即可访问不变的数据,因此,无论是在SMP共享内存系统(当今的所有多核系统)还是在松散捆绑的集群中,并发性都得到了增强。


3
函数式编程的支持者将最大的压力放在了第三点,即并发编程更容易。
Mchl 2011年

4
@Mchl:根据我的经验,他们将重点放在“更容易理解和推理”上,这对应于1。尽管我认为这在语言社区之间可能有所不同。
sepp2k 2011年

+1,非常完整的答案。@ sepp2k:两者都很重要。关于程序的推理是我们每天要做的事情,而且的确,如果您不必检查某些深层隐藏函数的状态是否已更改,那么仅阅读高级方法并了解正在发生的事情就容易得多。硬件方面:由于我们越来越趋向于多核和多处理器(尽管我想家用计算机获得多处理器还需要一段时间),因此拥有一种有助于并发编程的语言是一种溢价。
Matthieu M.

很好的答案,我想应该是#2,尽管我经常阅读有关多处理优势的信息,但很少有人说它很出色。
ocodo 2011年

1
@Yttrill,函数式语言依赖于垃圾回收并不是唯一的方法,当您处理不可变数据时,垃圾回收要容易得多。在基于指令的体系结构上进行任何计算都意味着修改状态,但这并不意味着功能语言在某种程度上很难并行化。功能性语言在并行性上摇摆不定;查找数据与Haskell并行,这是几乎不可能将其添加到命令式语言中的功能。
dan_waterworth 2012年

4

这是另一个优点:减少耦合。如果您有如下代码:

 function doStuff(x) { return x + y;}

在其他地方,您可以:

 function doOtherStuff(x) { y++; return y + x;}

则这两个函数是隐式相关的。没有简单的方法可以告诉您呼叫doStuff受到呼叫的影响doOtherStuff。如果没有可变状态,则必须使连接明确。

当然,这不是所有可变状态都存在的问题,而是普遍性可变状态都存在的问题。真正的解决方案是在默认情况下具有不变性,并通过某种方式“标记”并将可变状态限制在您需要的位置。


+1。许多经验丰富的程序员知道不要像上面那样编写代码,从“在这种情况下可变状态很糟糕”到“让我们认真减少我们可变的状态数量并编写更多功能的代码”并不是一个巨大的步骤,但这是一个步骤令人失望的是很少有。
dan_waterworth 2012年

2

简化的答案是:当您以纯功能语言看到名称时,只需简单地查找其定义即可知道相关的值。如果您具有可变变量,则只能通过最后执行几个分配中的哪个来区分,因此您还必须分析控制流,而控制流又可能是有条件的,从而给您带来多种可能性。要获得指数级爆炸,您只需考虑分配的RHS本身取决于变量,因此您也必须递归分析它们。

上面分析的底线是,没有注释来解释意图,不变量和语义是站不住脚的:这些可能难以解释,并且可能很难验证语义是否在实际代码中得到遵守。

这个答案基本上是@Javier点1的扩展。

我认为这也是对欺诈性OO机制的流行的一种解释:使用OO封装了可变状态,通过在某种程度上定位突变并允许更健壮的语义表达和验证,可以使分析变得更加容易。

已经指出,函数式编程不是答案。正确的答案是同时支持归纳(功能性)和协和(程序性)编程的系统,因此正确的工具可以处理无状态和有状态编程。仅仅是建设性的(功能性)理论已经建立,而状态管理理论仍处于起步阶段。


Haskell确实将功能性和命令性编程混合在一起-正常功能是功能性的,而有状态计算则可以用do表示法表示,让您仔细隔离和控制可变状态(除其他外)。这就是为什么使用最实用的STM实现的语言是Haskell的原因
蒂洪

注记本质上实际上并没有任何东西可以进行状态计算。在单子函数管道之上,Do-notation只是一种更简单的语法。有状态计算只是可以使用monad表示的事物之一,因此也可以使用do表示法。
乔纳森·斯特林

混合功能和命令式编程几乎是现有每种语言的功能。Haskell可能提供了一种隔离有状态部分的方法,但这并不能使其成为适当的组合:慈善机构更像是应有的状态(IMHO)。
Yttrill 2012年

2

作为用Haskell编写的DBMS Siege的作者,有些人可能认为我对可变状态的观点存在冲突。我希望能证明其他情况。

可变状态的目的是描述系统所处的当前状态。假设您有一个博客,并且它是数据库的后端,则数据库描述了查询时您在博客上的帖子。它。现在有多少个帖子?

将此与用于传达事实的不可变状态进行对比。8月12日有多少个帖子?

事实很容易推断,可变状态不是。但是,可变状态并不是我们应该消除的一些邪恶的不纯效果;我们经常需要它在我们生活的可变世界中共存,我们只需要更谨慎地使用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.