Hacker News new | ask | show | jobs
by fadelakin 3694 days ago
Can someone explain to me the main differences between a language like Common Lisp and Haskell?

I'm planning on learning on a purely functional language this year and I've narrowed it down to Haskell and CL but I don't know which to pick. Haskell has sort of been winning due to my friends knowing it and using it.

If you have any resources as well, please let me know. I don't know if this is the right place to post this.

9 comments

Common Lisp is not a purely functional language.

The most caracteristic feature of Lisp in general is that, its whole syntax is the literal representation of one of it's core datatypes, the linked list. This allows for creating idioms of arbitrary complexity and reusable abstractions with ease, one a tiny kernel.

Another wording of this is that the Lisp family of languages represent their programs as data that those programs directly manipulate, and thus, programs can manipulate themselves. This is homoiconicity.

For who likes laconicisms, Lisp is a pleasant way to write and execute a parse tree.

The advantage to this is that you can create syntactic abstractions that fit in nicely, that work on structured data instead of strings not parsed and verified yet (hey CPP!) and are reusable by other abstractions.

The disadvantage is that your set of abstractions can become very easily dialects, and the language ecosystem is prone to (and damned by) fragmentation (i.e. every Scheme has it's own module system, and then there's a late standard that nobody uses).

Another advantage of Lisp, though not unique to it neither theoretically nor practically, is the image, that is, the state of the interpreter. Your average Lisp process is code running on a Lisp VM, and the VM allows you to modify the running code. This allows you to pause the thread when an exception happens, modify the code, and play it again, and the program uses the new, modified version of the code. These are called restarts and supported at least in Steel Bank Common Lisp, and are well integrated into SLIME, the canonical Emacs mode for Common Lisp and other uncommon (!) lisps. This is so powerfull, I read that in one space mission, when they spotted a bug in the code of a research apparatus already in space, they connected to its image and hotpatched the code fixing the bug, saving NASA millions of dollars.

"its whole syntax is the literal representation of one of it's core datatypes, the linked list"

"Your average Lisp process is code running on a Lisp VM, and the VM allows you to modify the running code"

Thank you. As a non-Lisper, this is probably the clearest explanation of Lisp's qualities I've ever read.

> Your average Lisp process is code running on a Lisp VM, and the VM allows you to modify the running code.

Just for others reading this; this is correct, but note that it is typically not a bytecode based VM like the JVM, but rather running native code.

CL is not purely functional language.

CL is either multi-paradigm language or Lisp paradigm language. There is lisp style programming.

It has many functional primitives but typical CL programmer is not programming functionally. Other languages like Scheme or Clojure are more functionally 'oriented' Lisps.

Ah I see. I guess I got confused somewhere. Thanks for the clarification.
As others have mentioned, CL is not a pure functional language like Haskell.

However it is possible in CL to write parts of many programs in a functional style. Further, my functional collections library, FSet [0], greatly expands the amount of code that can be written this way, bringing CL much closer to being a functional language. One FSet user told me that it had changed the way he thinks about programming in CL -- which I think reflects an intellectual transition that is at least a good part of the transition one would hope to make by learning Haskell.

If you do go with CL, you might want to check it out. (It's in Quicklisp as "fset".)

[0] https://github.com/slburson/fset

Common Lisp is functional in the sense of being based on Lambda calculus, but with all sorts of imperative and OO things bolted on.

Haskell is functional in the sense most people think (maths 'n things, functions with no side effects), with a few 'outs' (monads or 'containers' for doing imperative-like things).

If you want a 'functional' language, choose Haskell. If you want a language you can bend to your will, where you'll be making your own abstractions, writing a DSL, etc..., choose Common Lisp. Actually Haskell isn't even bad for that, so if your friends are using Haskell, just try that.

One of the most important differences is the type system of Haskell vs. the dynamic typing of CL. This is not a trivial distinction and they are quite different ways to program.
You can write purely functional programs in CL, but it's not a purely functional language in the way haskell is, and I think most people don't use it that way.
As others said, code-as-data and macros are probably the big ones but there's also a difference in composability vs configuration as Chris Done explained very nicely: http://chrisdone.com/posts/haskell-lisp-philosophy-differenc...
To say it more correctly (hopefully): Haskell contains a purely functional sub-language. It also has impure parts (provided by monads). Just like most programming languages have pure and impure parts. The difference is that Haskell employs the type system to segregate the two parts.
> It also has impure parts (provided by monads).

Since we're going for precision, I note that monads have nothing to do with impurity (https://wiki.haskell.org/What_a_Monad_is_not#Monads_are_not_...). It just happens that IO, in which the impurity lives, is a monad. It is also a functor (in the category-theory, not Prolog or C++, sense), but that doesn't make functors impure, and it doesn't make monads impure (or impurity inherently monadic: https://wiki.haskell.org/What_a_Monad_is_not#Haskell_doesn.2...).

Alright, so let me phrase it this way then?:

> To say it more correctly (hopefully): Haskell contains a purely functional sub-language. It also has impure parts. Just like most programming languages have pure and impure parts. The difference is that Haskell employs the type system to segregate the two parts.

(Anyway I'd be interested in how to access IO without using the IO monad; is there a lower-level type to use instead?)

For anyone reading "functor" and moving on, this (http://www.catonmat.net/blog/on-functors/) is a great post discussing how the term is used in a variety of languages.
Go with your friends. That will make 100x the difference that any technical difference does. Same with any language really.