Haskell,Lisp和详细
对于那些在Haskell和Lisp方面有经验的人,我很好奇在Haskell和Lisp中编写代码是多么“愉快”(用一个可怕的术语)。
一些背景:我现在正在学习Haskell,之前曾经在Scheme和CL上工作过(还有一些进入Clojure)。 传统上,你可以认为我是dynamic语言的粉丝,他们提供的简洁和快速。 我很快就爱上了Lisp的macros,因为它给了我另一种避免冗长和样板的方法。
我发现Haskell 非常有趣,因为它向我介绍了我不知道存在的编码方式。 它肯定有一些方面,似乎有助于实现敏捷性,如易于编写部分function。 然而,我有点担心失去Lispmacros(我想我失去了它们;事实上被告知我可能还没有学到它们呢?)和静态分类系统。
那些在这两个世界上都做了大量编码的人,会不会介意经验的不同,你更喜欢哪一个,如果说偏好是情境的话?
简短的回答:
- 几乎任何你可以用macros来做的事情,你可以用一个更高级的函数来做(我包括单子,箭头等等),但是它可能需要更多的思考(但只是第一次,而且很有趣,你会成为一个更好的程序员),和
- 静态系统是足够一般的,它永远不会妨碍你,有点令人惊讶的是它实际上“有助于实现敏捷性”(如你所说),因为当你的程序编译时,你几乎可以肯定是正确的,所以这个确定性让你尝试你可能会害怕尝试的东西 – 编程有一个“dynamic”的感觉,尽pipe它与Lisp不一样。
[注:有一个“ 模板Haskell ”,可以让你像Lisp一样编写macros,但严格来说,你永远不需要它。]
首先,不要担心丢失dynamictypes等特殊function。 由于您熟悉Common Lisp,这是一个非常精心devise的语言,因此我认为您知道语言不能简化为其function集。 这完全是一个连贯的整体,不是吗?
在这方面,Haskell和Common Lisp一样明亮。 它的function结合在一起,为您提供了一种编程方式,使代码变得非常简短和优雅。 macros的缺乏可以通过更复杂(但同样更难理解和使用)概念(如monads和arrow)来减轻。 静态types系统增加了你的能力,而不像在大多数面向对象的语言中那样陷入困境。
另一方面,Haskell的编程与Lisp的交互性要差得多,Lisp等语言中存在的大量reflection并不适合Haskell预设的世界的静态视图。 因此,这两种语言的工具集有很大不同,但很难相互比较。
我个人更喜欢Lisp的编程方式,因为我觉得它适合我更好的工作方式。 但是,这并不意味着你也一定要这样做。
Haskell中的元编程需要比Common Lisp更less,因为很多可以围绕monad来构造,并且附加的语法使得embedded式DSL看起来不像树,但是总是存在如ShreevatsaR所提到的Template Haskell,甚至是Liskell (Haskell语义+ Lisp语法)如果你喜欢括号。
关于macros,下面是一个讨论它的页面: Hello Haskell,Goodbye Lisp 。 它解释了一个在Haskell中不需要macros的观点。 它带有一个比较的简单例子。
需要LISPmacros以避免评估两个参数的示例情况:
(defmacro doif (xy) `(if ,x ,y))
Haskell没有系统地评估两个参数的例子,没有像macros定义那样的需要:
doif xy = if x then (Just y) else Nothing
瞧
我是一个Common Lisp程序员。
前段时间尝试Haskell后,我的个人底线是坚持CL。
原因:
- dynamicinput(检查dynamic与静态input – 由Pascal Costanza进行的基于模式的分析 )
- 可选和关键字参数
- 统一的homoiconic列表语法与macros
- 前缀语法(不需要记住优先级规则)
- 不纯,因此更适合快速原型devise
- 强大的对象系统与元对象协议
- 成熟的标准
- 广泛的编译器
哈斯克尔当然有其自身的优点,并以一种完全不同的方式做一些事情,但从长远来看对我来说并没有削减。
在Haskell中,你可以定义一个if函数,这在LISP中是不可能的。 这可能是因为懒惰,它允许程序中有更多的模块化。 这篇经典文章:John Hughes 为什么selectFP ,解释了懒惰如何提高可组合性。
在我继续Haskell学习之旅的过程中,似乎帮助“replace”macros的一件事是定义自己的中缀操作符并定制其优先级和关联性的能力。 有点复杂,但一个有趣的系统!
在Lisp中,有很多非常酷的事情,用Haskell中的macros很麻烦(如果可能的话)。 以“memoize”macros为例(见Peter Norvig的PAIP第9章)。 有了它,你可以定义一个函数,比如foo,然后简单地评估(memoize'foo),它用一个memoized版本replacefoo的全局定义。 你能用Haskell在高阶函数中达到同样的效果吗?