我最近一直在学习函数式编程(特别是Haskell的,但我已经通过在Lisp和Erlang的教程走为好)。当我发现这些概念很受启发,我还没有看到“无副作用”的理念务实的一面。它有什么实际的好处?我试图想在功能心态,但也有一些情况,只是似乎过于复杂而不保存在一个简单的方法状态的能力(我不认为Haskell的单子“容易”)

是否值得继续学习深入的Haskell(或另一种纯粹的功能语言)?是功能还是无编程实际上比过程更富有成效?是不是有可能,我会在以后继续使用哈斯克尔或另一种功能性语言,或我应该学习它仅用于理解?

我不太在乎性能比生产力。所以我主要问我是否会比函数式语言更有效率是程序/面向对象/不管。

有帮助吗?

解决方案

读取函数编程果壳中

有很多优势,无国籍编程,其中最的是显着多线程和并行代码。说穿了,可变的状态是多线程代码的敌人。如果值是默认不可改变的,程序员不需要担心一个线程变异共享状态的两个线程之间的值,所以它消除了全班竞争情况相关的多线程错误。由于没有竞争条件,没有理由要么使用锁,因此不变性消除了另一个全班有关死锁以及错误的。

这就是很大的原因,函数式编程的问题,也可能是最好的一个用于跳跃的函数式编程的火车。也有很多的其它好处,包括简化调试(即函数都是纯和在应用程序的其他部分不发生变异状态),更简洁和表现代码相比,其严重依赖设计模式语言少样板代码,和编译器可以更积极地优化代码。

其他提示

在多块你的程序是无状态的,的更多的方式有把拼在一起,而无需任何破解。无状态模式的力量不在于无国籍(或纯度)的本身的,但它给你写强大,可重用的的功能,并结合他们的能力。

您可以找到很多的例子在约翰·休斯的文件的为什么函数编程事项(PDF)。

您会料滴更有效率,特别是如果你选择也具有代数数据类型和模式匹配(CAML,SML,Haskell中)。一个功能性的语言

很多其他的答案都集中在函数式编程,我相信这是非常重要的性能(并行)的一面。但是,你没有问具体的生产率,如,你可以在一个功能模式的速度比在命令式编程范式同样的事情。

其实我(个人经验)找到在F#是编程,我认为更好的方式相匹配,所以它更容易。我认为这是最大的区别。我编程两个F#和C#,而且也少了很多“战斗的语言”,在F#,这是我的爱。你不必去想在F#的细节。下面是什么我发现我真的很喜欢的几个例子。

例如,尽管F#是静态类型(所有类型都在编译时解析),类型推理计算出你有什么类型的,所以你不必说出来做。如果它不能弄清楚,它会自动让你的函数/类/不管通用的。所以你再也不用写任何通用的什么,这都是自动的。我发现,这意味着我花更多的时间思考这个问题,少如何实现它。事实上,每当我回来到C#,我发现我真的很想念这种类型推断,你永远不知道它是多么让人分心,直到你不需要再做下去了。

此外,在F#,而不是写循环,可以调用函数。这是一个微妙的变化,但显著,因为你不必去想循环结构了。例如,这里有一段代码,这将经历和匹配的东西(我不记得是什么,它是从项目欧拉拼图):

let matchingFactors =
    factors
    |> Seq.filter (fun x -> largestPalindrome % x = 0)
    |> Seq.map (fun x -> (x, largestPalindrome / x))

我认识到,做一个过滤器,然后映射(这是每个元素的转化)在C#是很简单,但你必须考虑在较低的水平。特别是,你必须写循环本身,并有自己明确的if语句,而那些各种各样的东西。由于学习F#,我已经意识到我发现它更容易在功能的方式,在这里,如果你想过滤,你写的“过滤器”的代码,如果你想图,你写的“地图”,而不是实施每一个细节。

我也爱|>运营商,我认为从ocaml的分离F#,和其他可能的函数式语言。这是管道操作符,它可以让你“管”一个表达式的输出转换成另一种表达的输入。这使得代码跟随我是怎么想的更多。就像上面的代码段,这是说,“拿因素序列,将其过滤,然后映射它。”这是思维的一个非常高的水平,这是因为你太忙着写循环和if语句你不命令式编程语言得到。这是一两件事,我最想念每当我进入另一种语言。

所以只是一般,即使我可以在C#和F#编程,我觉得它更容易使用F#,因为你能想到在一个较高的水平。因为较小的细节从功能编程除去我认为(在F#至少),我比较生产力。

修改:我在你问的函数式编程语言的“状态”的例子意见的人看到。 F#可以写势在必行,所以这里的你如何在F#可变状态直接例如:

let mutable x = 5
for i in 1..10 do
    x <- x + i

考虑所有你已经花了很长一段时间的调试困难的错误。

现在,那些如何臭虫很多是由于节目的两个单独的部件之间的“非故意的相互作用”? (几乎所有的线程错误有这样的形式:包括写共享数据,死锁的比赛,......另外,是很常见的发现,对全球状态的一些意想不到的效果库,或读/写注册表/环境等)< EM> I 将断定,至少1/3的“硬错误”属于这一类。

现在,如果你切换到无国籍/不变/纯粹的编程,所有这些bug消失。你都带有而不是一些新的挑战(例如,当你的的希望不同的模块与环境互动),但在象Haskell语言,这些交互得到明确具体化入式系统,这意味着您可以只看一个关于它可以具有与该程序的其余部分交互的类型的函数和原因的类型。

这是从“永恒” IMO以大取胜。在一个理想的世界,我们都会设计出色的API和即使事情是可变的,影响将是局部的和良好的记录,并“意外”的互动将保持在最低限度。在现实世界中,有很多是在无数的方法与全局状态交互的API,而这些是最有害的错误的根源。有志无国籍被有志于部件之间摆脱无意识的/隐式/后面的幕后的相互作用。

的无状态函数的一个优点是,它们允许预计算或函数的返回值的高速缓存。即使是一些C编译器允许你明确地标记功能无状态,以提高他们的optimisability。正如许多人所指出的,无状态的功能更容易parallelise。

但是效率不是唯一的问题。纯函数是因为任何影响它明确规定更容易测试和调试。而在功能性语言编程时,一个在做尽可能少的功能,“脏”的习惯得到(与I / O等)成为可能。这样分离出状态的东西是设计方案的好方法,即使是在不那么函数式语言。

函数式语言可能需要一段时间来“搞定”,这是很难解释的人谁没有完成这一过程了。但是,谁坚持足够长的时间终于大多数人意识到做文章是值得的,即使他们最终不会使用功能的语言了。

无状态,这是很容易地自动并行化代码(如CPU上有越来越多的内核,这是非常重要的。制造)。

我写了只是这个问题后一段时间回来:关于纯度中的重要性。

,当你开始具有较高交通无国籍web应用是必不可少的。

有可能是很多,你不希望存储对例如安全原因,客户端的用户数据。在这种情况下,你需要将它存储服务器端。您可以使用Web应用程序默认的会话,但如果你有应用程序的多个实例,您将需要确保每个用户总是指向同一个实例。

负载平衡器常常必须有“粘性会话”,其中负载平衡器一些如何知道要发送的服务器的用户请求的能力。这不是理想的,虽然,例如,它意味着每次重新启动您的Web应用程序,所有连接的用户将失去其会话时间。

有一个更好的方法是会话存储在某种类型的数据存储的Web服务器后面,这几天有可用的巨大的NoSQL产品负荷为这个(Redis的,蒙戈,elasticsearch,memcached的)。通过这种方式,web服务器是无状态的,但你仍然有状态的服务器端和这个国家的可用性可以通过选择合适的数据存储设置进行管理。这些数据存储通常有很大的冗余,所以它应该总是有可能修改你的web应用,甚至是数据存储,而不会影响用户。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top