我一直在阅读Doets和Eijck 2004年的《Haskell之路:逻辑、数学和编程》。这似乎是一本备受尊重的书,但当它声称Haskell是Lisp家族的成员时,我很吃惊。这是否准确?我认为Lisps具有s表达式、不纯函数和列表作为唯一的复合数据结构。Haskell没有这些特点。对于这种说法有什么正当理由吗?
我一直在阅读Doets和Eijck 2004年的《Haskell之路:逻辑、数学和编程》。这似乎是一本备受尊重的书,但当它声称Haskell是Lisp家族的成员时,我很吃惊。这是否准确?我认为Lisps具有s表达式、不纯函数和列表作为唯一的复合数据结构。Haskell没有这些特点。对于这种说法有什么正当理由吗?
Lisp是一个非常模糊的概念。我看到两个或多或少有用的解释:
Lisp是一组共享某些共同思想的语言家族。在广义解释中,属于这个家族的语言非常不同:Common Lisp、Scheme、Logo、Dylan、Emacs Lisp、Clojure、RLisp、3Lisp等等。
Lisp是一系列实现核心语言(CAR、CDR、CONS、LAMBDA、PROG、SET、SETQ、QUOTE、DEFUN、IF、COND、DO等)的语言的血统:Lisp 1.5、MacLisp、Lisp Machine Lisp、Emacs Lisp、Common Lisp、ISLisp。请注意,这些语言通常都将“Lisp”作为其名称的一部分。
一些Lisp方言中的典型事物包括:严格评估、副作用、直接命令式编程、函数编程结构、s表达式、宏展开。
Haskell是一种非常不同的语言:非严格评估、语法不基于s表达式、静态类型、纯函数式。
Haskell既不符合1也不符合2。因此,我会说Haskell不是Lisp。
类似地,我们可以说一个函数式编程语言是:
支持函数式编程的语言:Lisp、APL、...、ML、SML、OCAML、F#、Miranda、Haskell等。
强制执行函数式编程的语言。在这方面,Lisp已经不是很适合了,因为命令式甚至面向对象编程在Lisp中并不是二等公民。
强制执行纯函数式编程的语言。在这里,我们有Haskell作为一个很好的例子。作为相对较新的Lisp方言之一,Clojure也可能适合。
通常,Lisp只支持,但不强制执行函数式编程。因此,在更广泛的解释下,它是一种函数式编程语言。
Haskell是被视为一种纯函数式编程语言之一。
在对编程语言进行分类时,将它们分为两组是有意义的:从FORTRAN衍生出来的语言和非FORTRAN衍生出来的语言。 1958年,“非FORTRAN组”基本上意味着LISP(至少在今天没有灭绝的语言中)。 因此,一段时间以来,编程语言家族树有两个主要分支:FORTRAN后代和LISP后代。 如果这些是唯一的两个选择,那么我会将Haskell放入LISP分支。
然而,许多评论人士认为,诸如ML、Prolog和APL等语言是“突然冒出来的”——引入了足够独特的范例,以至于有自己的谱系。 Haskell显然与ML有关。
作为这种分类的例子,请参见以下编程语言家族树:
O'Reilly's Programming Language Poster
我认为Haskell确实是一种Lisp,因为它们都基于λ演算。 Haskell是λ的实现。
尽管大多数人会说Haskell属于ML系列。 ML也基于λ,我知道的所有函数语言也是如此。
在底层中,OCam(来自ML的后代)被编译成组合逻辑(combinatory logic),这是一种等效于λ演算的形式化语言,并由Haskell Curry发明,后来Haskell也以他的名字命名。但是现在似乎使用组合逻辑进行函数语言编译的情况较少,所以我不确定像GHC这样的现代编译器是否仍然使用组合逻辑。
Lisp的语法与λ演算几乎相同,这使得这个家族(Scheme、Clojure等)非常特殊。
cons
car
cdr
cond
eq
atom
and
or
not
nil
Haskell 不符合前三个特点,它的宏 (Template Haskell) 不遵循代码即数据的范例,虽然列表非常重要,但它们并不是主要的数据结构。
所以我会说不,Haskell 不是 Lisp。
在我看来,Lisp是一种语言,其中源代码是该语言中有效的结构。
Haskell的源代码不是Haskell中有效的结构,因此它们必须有一个单独的语法(Haskell模板)来操作自己的源代码。
但是,Haskell中有至少一个有趣的特性让我想起了Lisp。那就是函数调用的语法:func args1 agr2 arg3。Lisp也有完全相同的语法:(func args1 agr2 arg3)。实际上,你也可以在Haskell中包含外部括号。所有其他Algol家族语言在函数名和参数之间引入括号和逗号。
我想说这两种语言都是函数式编程语言,这使它们属于同一类别。但是我不会把Haskell称为Lisp的派生语言(像Scheme一样)。
可以说,所有函数式编程语言都是Scheme的后代,因为Scheme大致实现了lambda演算(虽然有些古怪),而函数式编程语言也实现了lambda演算,尽管它们不一定总是看起来像。同样可以说,ML的血统完全不同,因为它追溯到Landin的ISWIM,这对Lisp几乎没有影响,从一开始就知道它的理论基础。
真正的问题是Haskell和Lisp彼此比与C族或Prolog族中的任何一种更相似。
我本来会认为人们应该忽略语法问题,但我忘了Lispers把语法定义为成为lisp的一个关键部分。我觉得这很傻,因为按照这个标准,可以说Haskell不是Lisp,但Liskell是,尽管后者基本上只是前者的处理器。