最纯正的函数式编程语言?[关闭]


20

我对更好地学习函数式编程感兴趣。为此,看来我应该强迫自己使用最纯净的函数式编程语言。因此,我在这里或多或少地要求根据功能性编程语言的纯度对其进行排序。

在我看来,学习Lisp或Clojure(或Scheme或Scala等)会更加实用,但是就我最近所听到的信息而言,Haskell在向某人教授函数式编程原理方面很难被击败。我还不确定,所以我问你:哪一种是最纯粹的函数式编程语言?如果有几个人争夺最纯粹的函数式编程语言的宏伟标题,那么排序将是很棒的。


2
我学会了米兰达在大学,所以我偏动,但我会建议哈斯克尔到任何人想要沉浸在函数式语言无杂念杂质。* 8')
Mark

2
学习完函数编程之后,您还应该学习具有表现力的类型系统的静态类型编程。在组合类别(功能性和类型性)中,我建议:Coq> Haskell> OCaml> Scala>其他。Coq和Haskell之间有一些不太受欢迎的替代方案(例如Epigram和Agda)。Haskell错过了OCaml的表达模块系统。
lukstafi 2013年

Answers:


28

没有用于评估功能语言纯净程度的量表。如果语言允许副作用,那是不纯的,否则就是纯粹的。根据这个定义,Haskell,Mercury,Clean等都是纯函数式语言;而Scala,Clojure,F#,OCaml等是不纯洁的。

编辑:也许我应该这样说:“如果语言在不让类型系统知道的情况下不允许出现副作用,那是纯粹的。否则就是不纯净的。”


6
不太完全:Haskell确实有副作用(IOmonad)。只是将导致副作用的代码清楚地标记为这样。我认为完全不讲纯净/不纯洁的语言是没有用的(Haskell让您必须进行编程!加斯普!),但将代码块(函数,模块,程序等等)讲纯净仍然有用。 /不纯。
Frank Shearar 2010年

8
@弗兰克:是的,Haskell确实允许产生副作用,但是它不仅标记了引起副作用的代码。即使使用引起副作用的代码,它也保持引用透明性,这就是它的纯粹意义-至少根据许多人对纯度的定义而言。当然,这与missingfaktor对“不允许的副作用”的定义不符。
sepp2k 2010年

4
@Frank Shearar,但是以这种方式讲话很有用,因为IOmonad 纯净的。它不是运行时库,不是您的代码,因为您的main函数基本上是一个巨大的状态转换器。(有点像main :: World -> World幕后花絮)
另一种方式是

1
我的语言也具有参照透明性。您只需编写program = "some C code",然后运行时环境处理C代码。:-)
Daniel Lubarov 2011年

3
由于打印到屏幕是一种副作用,真正的纯功能程序非常无聊。

15

由于学习是您的目标,而不是自己编写程序所以没有比Lambda Calculus更纯净的了。

Lambda微积分技术是在计算机发明之前就出现的。需要一些熟练的逻辑学家来研究如何进行减法(理论上有一段时间,只有加法和乘法才是可能的)。

学习布尔值和数字,以及如何if从看似没有的发明中发现布尔值和数字,并不会在您的油箱中放更多的汽油,但这会使您的油箱更大。


当然,可能没有比这更纯净的方法了,但是我们在数学上的障碍有点过分了。我仍然想练习编程并学习新语言,同时吸收功能原理。但是,我同意研究lambda演算可能只是为了更好地理解功能范式的基础(并且具有更大的容器)可能会很有趣。
Joanis 2010年

2
编写证明就是编写程序,编写程序就是编写证明。当您了解有关Curry-Howard同构的知识时,您会意识到自己在一万行之前就已经通过了数学障碍。
Macneil 2010年

1
没有简单的表示形式-1
Daniel Lubarov 2011年

2
@梅森·惠勒:仅λ演算没有数字,或者除了lambda抽象外,实际上没有任何类型的数据。除非另有说明,否则任何在λ微积分中谈论数字的人都可能表示Church对自然数的编码,其中数字n由n倍函数组合表示。这就是说,我怀疑这是那个太大的斗争搞清楚减法一旦有人真的试图; 我只在加法的定义下知道了减法是可能的,所以我自己一个下午就解决了。
加利福尼亚州麦肯

1
一旦按情况分解,使用教堂数字减法就很容易了。建立整个(派生的)演算以支持负数,而需要做更多的工作。
多纳研究员

6

不纯净的语言在原理上与更熟悉的指令式语言并没有真正的区别,特别是现在已经复制了许多功能技巧。风格不同-解决问题的方式。

无论您是将Haskell视为纯元素,还是将IO monad视为杂质,Haskell样式都是这种样式的一种极端形式,值得学习。

Haskell IO monad源自(当然)monad的数学理论。但是,对于命令式程序员来说,我认为倒退的方式到达monad更有意义。

第一阶段-一种纯函数式语言可以轻松地返回一个大字符串值作为结果。这个大字符串可以是命令式程序的源代码,它是从某些需求指定参数以纯功能方式导出的。然后,您可以构建一个运行代码生成器的“高级”编译器,然后将生成的代码自动送入命令式语言编译器。

第二阶段-您将生成一个强类型抽象语法树,而不是生成文本源代码。您的命令式语言编译器被“高级”编译器所吸收,并直接接受AST作为源代码。这与Haskell所做的非常接近。

但是,这仍然很尴尬。例如,您有两种截然不同的函数-在代码生成阶段评估的函数和在生成的程序运行时执行的函数。有点像C ++中函数和模板之间的区别。

因此,对于阶段3,使两者相同-具有相同语法的相同函数可以在“代码生成”过程中部分评估,或者完全评估,或者根本不评估。进一步,丢弃所有循环构造AST节点,以利于递归。实际上,将AST节点的想法完全丢弃为一种特殊的数据-不具有“文字价值”的AST节点,而仅具有值等。

这几乎是IO monad所做的-绑定运算符是一种构成“动作”以形成程序的方式。没什么特别的-只是一个功能。在“代码生成”过程中可以评估许多表达式和函数,但是那些依赖I / O副作用的表达式和函数必须将评估推迟到运行时-不受任何特殊规则的限制,而是由于数据依赖关系的自然结果。表达式。

通常,Monad只是一般化-它们具有相同的接口,但实现抽象操作的方式有所不同,因此,它们不评估命令式代码的描述,而是评估其他内容。具有相同的界面意味着您可以对monad进行某些操作,而无需关心哪个monad,这很有用。

这种描述无疑会使纯粹主义者大开眼界,但是对我来说,它解释了Haskell之所以有趣的一些真实原因。它模糊了编程和元编程之间的界限,并使用功能性编程工具来重新设计命令式编程,而无需特殊的语法。

我对C ++模板的批评是,它们是命令式语言中一种破碎的纯函数子语言-要在编译时而不是在运行时评估相同的基本功能,您必须使用完全不同的样式重新实现它编码。在Haskell中,虽然杂质必须按其类型进行标记,但可以在同一程序中的元编程意义上和运行时非元编程意义上评估完全相同的功能-没有硬性规定在编程和元编程之间。

就是说,有些Haskell无法做一些元编程的事情,主要是因为类型(也许还有其他一些东西)不是一流的值。但是,有一些语言变体试图解决这个问题。

我对Haskell所说的很多事情都可以用在不纯函数语言中,甚至有时甚至是祈使语言中。Haskell有所不同,因为您别无选择,只能采用这种方法-它基本上迫使您学习这种工作方式。您可以“用ML编写C”,但不能“用Haskell编写C”-至少要在不了解引擎盖底层的情况下才能做到。


谢谢!我想知道C ++模板的通用性是否可以统一到函数本身中。看起来Haskell可以做到这一点,但是重要的部分是它是否可以用编译语言来实现,以便同一引擎在编译时从模板创建通用函数,也可以在运行时对其进行评估……
Milind R

5

我个人将语言分为三种功能纯度:

  • 纯函数式语言 -即那些将整个程序视为纯函数并仅通过与运行时交互来处理可变性的语言-Haskell可能是典型的示例

  • 不正确的功能语言 -即那些强调功能样式但允许副作用的语言。Clojure显然属于这一类(它作为STM框架的一部分,允许以受控方式进行突变),也包括OCamlF#

  • 多范式语言 -这些不是最重要的功能语言,但是可以通过使用一流的函数等来支持功能样式。Scala是一个很好的例子,我也将Common Lisp归入此类,您甚至可以包括像JavaScript这样的语言

根据您的情况,建议您先学习Haskell,然后再学习Clojure。这就是我所做的,对我来说非常有效!Haskell非常漂亮,可以教给您最纯粹的功能原理,Clojure更加务实,可以帮助您完成很多工作,同时仍能发挥很多功能。

我并没有把第三类算作功能语言(尽管在学习了Haskell和Clojure之后,我经常发现自己在使用它们时会利用功能技术!)


非常严格的限制内,甚至C都具有功能。(主要限制在于函数的运行时综合,这在C语言中确实是可怕的,以至于大多数人声称它无法完成。)
Donal Fellows

2
@Donal研究员:在无聊到无穷的极限内,每种图灵完备的语言都可以发挥作用:只需使用该语言实现Lisp解释器,然后使用它即可。:]
CA McCann

如果您认为所有图灵都已经完成,因此可以模仿其他一切,那么范例就毫无意义。当您想到范例时,您必须专注于语言使习惯用法成为什么以及它阻止/阻止了什么。在我看来,要算作功能语言,突变和副作用必须是单项的(对于不纯的FP)或禁止的(对于纯FP)。这意味着C不起作用。像Scala这样的多范式语言都不是。
mikera 2011年

@mikera:我发现您的答案非常有趣:如果Scala不是函数式的,而是仅是多范式的,您如何判断C ++ 11,C#甚至Java(计划中的lambdas)中的函数式编程功能?
乔治

@Giorgio:我认为您提到的所有语言中的功能特性可能是一个好主意,它们只是不使它们成为“功能语言”。或者从相反的方向来看它,您可以执行命令式单子IO的事实并不能使Haskell成为命令式语言:-)。当您将来自许多不同范例的要素组合在一起并且不首先考虑任何特定样式时,基本上就是多范例语言。恕我直言,C ++,C#和Java都朝着多范式迈进,但由于基于类的OOP仍然占主导地位,因此还没有完全实现。
mikera 2012年

3

如果纯函数式语言是这样的,那么它仅具有纯函数(没有副作用的例程),那么它就毫无意义,因为它无法读取输入或写入输出;)

因为这是真正的学习,我觉得隔离是不一定路可走。函数式编程是一种范例。重要的是要了解哪种范例适用于哪些问题,更重要的是,如何将它们最佳地组合起来。

我现在要说的是:编程方式既愚蠢又适得其反。唯一重要的是您的程序简短,易于编写,易于维护并且可以正确运行。如何实现这一点与编程时尚无关。- 理查德·琼斯

除此之外,如果您正在寻找“纯度”,则可能需要看一下Pure。但是请注意,调用C例程非常容易,使其在功能上不纯净(但也非常强大)。


3

不是一个完全严肃的答案,但是Unlambda必须成为竞争者。您不能获得比SKI组合器更多的“纯功能”。


4
疯狂!异端!哪种纯净的语言具有像副作用的组合词之类的荒谬性?不,不。你真的想在这里什么是懒ķ
CA McCann

2

Erlang,Haskell,Scheme,Scala,Clojure和F#

这个问题将可能是最好的,你帮助你在你的搜索为


谢谢,确实是一个有趣的问题。我从PLT-Scheme / Racket开始,但是我还没有看过SICP ...真实世界Haskell对我来说也很有趣。
Joanis 2010年

Scheme鼓励一种功能风格,但它确实具有set!(除其他外)...
Daniel Lubarov 2011年

我建议使用OCaml,因为它是我的最爱。它有一个模块系统,Haskell和F#错过了。
lukstafi

@lukstafi haskell可能在最近三年中发生了变化(我知道它变得疯狂起来),但是haskell中肯定有一些模块。
萨拉

@kai所谓的模块系统,是指由其他模块(模块的“ lambda演算”)参数化的模块。
lukstafi
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.