对于那些在Haskell和Lisp中都有经验的人,我很好奇是如何“愉快”(使用一个可怕的术语)是在Haskell和Lisp中编写代码。
一些背景知识:我现在正在学习Haskell,之前曾使用过Scheme和CL(还有一点涉足Clojure)。传统上,你可以认为我是动态语言的粉丝,因为它们提供了简洁和快速。我很快就爱上了Lisp宏,因为它给了我另一种避免冗长和样板的方法。
我发现Haskell 令人难以置信的很有趣,因为它向我介绍了我不知道存在的编码方式。它肯定有一些方面似乎有助于实现敏捷性,比如易于编写部分功能。但是,我有点担心丢失Lisp宏(我猜我失去了它们;事实上我可能还没有了解过它们吗?)和静态打字系统。
在这两个世界中做过大量编码的人是否会想到你喜欢的经历如何不同,以及所说的偏好是情境化的?
答案 0 :(得分:68)
简短回答:
[注意:有一个“Template Haskell”可以让你像在Lisp中一样编写宏,但严格来说你不应该需要它。]
答案 1 :(得分:63)
首先,不要担心失去动态类型等特定功能。由于您熟悉Common Lisp,这是一种设计精良的语言,我假设您已经意识到语言不能简化为其功能集。这一切都是关于一个连贯的整体,不是吗?
在这方面,Haskell的亮度与Common Lisp一样明亮。它的功能相结合,为您提供了一种编程方式,使代码非常简短和优雅。通过更复杂(但同样,更难以理解和使用)的概念,如monad和箭头,可以减轻宏的缺乏。静态类型系统增加了你的能力,而不是像大多数面向对象语言那样妨碍你。
另一方面,Haskell中的编程比Lisp更不具有交互性,而像Lisp这样的语言中存在的大量反射不适合Haskell预设的世界静态视图。因此,您可以使用的工具集在两种语言之间存在很大差异,但很难相互比较。
我个人更喜欢Lisp的编程方式,因为我认为它符合我工作的方式。但是,这并不意味着你也必然会这样做。
答案 2 :(得分:13)
在Haskell中对元编程的需求比在Common Lisp中少,因为很多可以围绕monad构建,并且添加的语法使得嵌入式DSL看起来不像树一样,但是ShreevatsaR提到了总是模板Haskell,以及如果你喜欢括号,请使用Liskell(Haskell语义+ Lisp语法)。
答案 3 :(得分:10)
关于宏,这是一个讨论它的页面:Hello Haskell, Goodbye Lisp。它解释了Haskell中不需要宏的观点。它附有一个简短的比较例子。
需要LISP宏以避免评估两个参数的示例情况:
(defmacro doif (x y) `(if ,x ,y))
Haskell没有系统地计算两个参数的示例情况,不需要像宏定义那样:
doif x y = if x then (Just y) else Nothing
瞧瞧
答案 4 :(得分:8)
我是Common Lisp程序员。
前段时间尝试过Haskell,我个人的底线就是坚持使用CL。
原因:
Haskell确实有自己的优点,并且以一种根本不同的方式做一些事情,但它并没有为我长期削减它。
答案 5 :(得分:6)
在Haskell中,您可以定义一个if函数,这在LISP中是不可能的。这是可能的,因为懒惰,允许程序更多的模块化。这篇经典论文:John Hughes撰写的Why FP matters,解释了懒惰如何增强可组合性。
答案 6 :(得分:4)
当我继续我的Haskell学习之旅时,似乎有一件事有助于“替换”宏是能够定义自己的中缀运算符并定制它们的优先级和关联性。有点复杂,但有趣的系统!
答案 7 :(得分:4)
你可以在Lisp中实现很酷的东西,在Haskell中使用繁琐的宏(如果可能的话)。以“memoize”宏为例(参见Peter Norvig的PAIP第9章)。有了它,你可以定义一个函数,比如说foo,然后简单地评估(memoize'foo),它用一个memoized版本替换foo的全局定义。你能用高阶函数在Haskell中达到同样的效果吗?