可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
For those of you experienced in both Haskell and some flavor of Lisp, I'm curious how "pleasant" (to use a horrid term) it is to write code in Haskell vs. Lisp.
Some background: I'm learning Haskell now, having earlier worked with Scheme and CL (and a little foray into Clojure). Traditionally, you could consider me a fan of dynamic languages for the succinctness and rapidity they provide. I quickly fell in love with Lisp macros, as it gave me yet another way to avoid verbosity and boilerplate.
I'm finding Haskell incredibly interesting, as it's introducing me to ways of coding I didn't know existed. It definitely has some aspects that seem like they would aid in achieving agility, like ease of writing partial functions. However, I'm a bit concerned about losing Lisp macros (I assume I lose them; truth be told I may have just not learned about them yet?) and the static typing system.
Would anyone who has done a decent amount of coding in both worlds mind commenting on how the experiences differ, which you prefer, and if said preference is situational?
回答1:
Short answer:
- 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.
[Note: There is a "Template Haskell" that lets you write macros just as in Lisp, but strictly speaking you should never need it.]
回答2:
First of all, don't worry about losing particular features like dynamic typing. As you're familiar with Common Lisp, a remarkably well-designed language, I assume you're aware that a language can't be reduced to its feature set. It's all about a coherent whole, isn't it?
In this regard, Haskell shines just as brightly as Common Lisp does. Its features combine to provide you with a way of programming that makes code extremely short and elegant. The lack of macros is mitigated somewhat by more elaborate (but, likewise, harder to understand and use) concepts like monads and arrows. The static type system adds to your power rather than getting in your way as it does in most object-oriented languages.
On the other hand, programming in Haskell is much less interactive than Lisp, and the tremendous amount of reflection present in languages like Lisp just doesn't fit the static view of the world that Haskell presupposes. The tool sets available to you are therefore quite different between the two languages, but hard to compare to one another.
I personally prefer the Lisp way of programming in general, as I feel it fits the way I work better. However, this doesn't mean you're bound to do so as well.
回答3:
There's less need for metaprogramming in Haskell than in Common Lisp because much can be structured around monads and the added syntax makes embedded DSLs look less tree-like, but there's always Template Haskell, as mentioned by ShreevatsaR, and even Liskell (Haskell semantics + Lisp syntax) if you like the parentheses.
回答4:
Concerning macros, here is a page which talk about it : Hello Haskell, Goodbye Lisp. It explains a point of view where macros are just not needed in Haskell. It comes with a short example for comparison.
Example case where a LISP macro is required to avoid evaluation of both arguments :
(defmacro doif (x y) `(if ,x ,y))
Example case where Haskell does not systematically evaluates both argument, without the need of anything like a macro definition :
doif x y = if x then (Just y) else Nothing
And voilà
回答5:
I'm a Common Lisp programmer.
Having tried Haskell some time ago my personal bottom line was to stick with CL.
Reasons:
- 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 does have its own merits of course and does some things in a fundamentally different way, but it just doesn't cut it in the long term for me.
回答6:
In Haskell you can define an if function, which is impossible in LISP. This is possible because of laziness, which allows for more modularity in programs. This classic paper: Why FP matters by John Hughes, explains how laziness enhances composability.
回答7:
As I continue my Haskell-learning journey, it seems that one thing that helps "replace" macros is the ability to define your own infix operators and customize their precedence and associativity. Kinda complicated, but an interesting system!
回答8:
There are really cool things that you can achieve in Lisp with macros that are cumbersome (if possible) in Haskell. Take for example the `memoize' macro (see Chapter 9 of Peter Norvig's PAIP). With it, you can define a function, say foo, and then simply evaluate (memoize 'foo), which replaces foo's global definition with a memoized version. Can you achieve the same effect in Haskell with higher-order functions?