Haskell, Lisp, and verbosity [closed]

本秂侑毒 提交于 2019-12-02 13:55:30

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.]

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.

Herrmann

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.

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à

Leslie P. Polzer

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.

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.

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?

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!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!