English 中文(简体)
Haskell、Lisp和冗长性
原标题:
  • 时间:2008-12-25 10:58:42
  •  标签:

对于那些既熟悉Haskell又熟悉某种Lisp语言的人来说,我很好奇在Haskell和Lisp中编写代码的“愉悦程度”(使用可怕的术语)。

一些背景:我现在正在学习Haskell,以前曾经使用过Scheme和CL(还有一小部分Clojure)。传统上来说,你可以认为我是动态语言的粉丝,因为它们能够提供简洁和迅速。我很快爱上了Lisp宏,因为它让我有另一种避免冗长和样板代码的方式。

我发现Haskell非常有趣,因为它向我介绍了我不知道存在的编码方式。它肯定有一些方面似乎可以帮助实现敏捷性,如编写部分函数的便利性。然而,我有点担心失去Lisp宏(我假设我失去了它们;说实话,也许我还没有了解它们?)和静态类型系统。

是否有人在两个世界中都编写了相当数量的代码,并愿意评论其经验的不同之处,您喜欢哪一个,并且该偏好是否情境相关?

问题回答

简短回答:

  • almost anything you can do with macros you can do with a higher-order function (and I include monads, arrows, etc.), but it might require more thinking (but only the first time, and it s fun and you ll be a better programmer for it), and
  • the static system is sufficiently general that it never gets in your way, and somewhat surprisingly it actually "aids in achieving agility" (as you said) because when your program compiles you can be almost certain that is correct, so this certainty lets you try out things you might be otherwise afraid to try -- there is a "dynamic" feel to programming although it s not the same as with Lisp.

注意:有"模板 Haskell"可以像 Lisp 一样编写宏,但严格来说您永远不应该需要它。

首先,不用担心失去动态类型等特定功能。因为你熟悉Common Lisp,这是一种非常精心设计的语言,我想你应该知道语言不能仅凭其特性来评估。这一切都是关于一个协调的整体,不是吗?

在这方面,Haskell的表现和Common Lisp一样出色。它的特性结合在一起,为你提供了一种编程方式,使得代码变得极为简短和优美。它缺少宏的问题在一定程度上得到了缓解,因为有更为复杂(但同样难以理解和使用)的概念,比如monads和arrows。静态类型系统增加了你的能力,而不像大多数面向对象语言那样阻碍你的发展。

另一方面,Haskell编程比Lisp互动性要少得多,而像Lisp这样的语言中存在的大量反射,与Haskell假设的静态世界观不相符。因此,两种语言可用的工具集非常不同,但很难相互比较。

我个人更喜欢Lisp的编程方式,因为我觉得它更适合我的工作方式。但是,这并不意味着你也必须这样做。

在Haskell中,相较于Common Lisp,元编程需求更少,因为许多内容可以围绕着Monad进行结构化,而新增的语法使得嵌入式DSL看起来不那么树状。但如ShreevatsaR所提及的,始终可以使用Template Haskell,甚至也可以使用Liskell(Haskell语义+Lisp语法),如果你喜欢用括号。

关于宏,这里有一个页面讨论它:Hello Haskell, Goodbye Lisp。它解释了一个观点,即在Haskell中宏是不必要的。它提供了一个简短的比较示例。

需要使用LISP宏来避免对两个参数进行求值的示例案例:

(defmacro doif (x y) `(if ,x ,y))

Haskell 不需要类似宏定义的东西,就能不系统地评估两个参数的示例情况:

doif x y = if x then (Just y) else Nothing

这就是了

我是一个通用Lisp程序员。

在一段时间前尝试了Haskell之后,我的个人底线是坚持使用CL。

原因:

  • dynamic typing (check out Dynamic vs. Static Typing — A Pattern-Based Analysis by Pascal Costanza)
  • optional and keyword arguments
  • uniform homoiconic list syntax with macros
  • prefix syntax (no need to remember precedence rules)
  • impure and thus more suited for quick prototyping
  • powerful object system with meta-object protocol
  • mature standard
  • wide range of compilers

当然,Haskell确实有其自己的优点,并且在根本上以一种不同的方式完成一些事情,但对我来说,它在长期内并不够用。

在 Haskell 中,您可以定义 if 函数,而在 LISP 中不可能。这是因为惰性,它允许在程序中实现更多的模块化。 John Hughes 的经典论文 为什么 FP 很重要 解释了懒惰如何增强可组合性。

在Lisp中,使用宏能够实现一些非常酷的功能,在Haskell中则需要复杂的方法(如果可能的话)。例如,可以考虑Peter Norvig的《人工智能编程》第9章中的"memoize"宏。使用这个宏,可以先定义一个函数,比如说foo,然后只需要简单地评估(memoize foo),就可以替换掉foo的全局定义,并得到一个带有记忆功能的版本。在Haskell中,是否可以使用高阶函数实现相同的效果呢?

随着我继续学习 Haskell 的旅程,似乎找到了一件可以“替代”宏的事情,那就是定义自己的中缀运算符并自定义它们的优先级和结合性。有点复杂,但是这是一个有趣的系统!





相关问题
热门标签