Live data from Hacker News

A difference between Haskell and Common Lisp

chrisdone.com

141–150 of 203 posts

Re: A difference between Haskell and Common Lisp

#141

The biggest difference between Haskell and Lisp is that Lisp is multi-paradigm, while Haskell is not. Haskell is more opinionated, and makes a bunch of decisions for you (that you can choose to work around/sugar/hack until Haskell looks like something else/does what you want). All the other things that Haskell comes with - strong typing, monads, lazy evaulation, can be written into common lisp, but whether you need t…

They can't be written in Lisp well, or at all. Strong typing with inference can't be bolted on. Monads that take advantage of this typing can't be bolted on. Changing Lisp to have lazy semantics across the board ain't gonna happen. You might be able to write a Haskell interpreter from scratch that interacts with the Lisp environment, but you can't feasibly transform Lisp itself.

Got to this late, but other commenters have already pointed out why this is wrong.

While this is unfounded (I have no sources), LISP is quite possibly the most flexible higher level language ever invented, I would caution against betting against it in the future.

Saying that it's the most flexible higher language ever invented might not actually amount to much -- I'm sure there's actually a small subset of features/points-in-the-language-that-allow-for-user-modifications that you need to achieve such high flexibility, but figured it was worth saying.

[EDIT] - My wording of the original post is sloppy. Where I say Lisp, I mean the dialect of Lisp that is Common Lisp.

Re: A difference between Haskell and Common Lisp

#142

Earlier quoted context omitted.

They can't be written in Lisp well, or at all. Strong typing with inference can't be bolted on. Monads that take advantage of this typing can't be bolted on. Changing Lisp to have lazy semantics across the board ain't gonna happen. You might be able to write a Haskell interpreter from scratch that interacts with the Lisp environment, but you can't feasibly transform Lisp itself.

Got to this late, but other commenters have already pointed out why this is wrong. While this is unfounded (I have no sources), LISP is quite possibly the most flexible higher level language ever invented, I would caution against betting against it in the future. Saying that it's the most flexible higher language ever invented might not actually amount to much -- I'm sure there's actually a small subset of features/p…

Your argument doesn't add anything really. You can make anything in any reasonable language.

When people say "you can add X to Common Lisp" or "you can make X in Common Lisp", they usually mean that you can integrate such a feature in Lisp.

If you mean "you can write a compiler in Lisp", then, obviously. But you can do that in C++ too.

Not a single reply has demonstrated that you can effectively and reasonably add those features (to their fullest extent) to Lisp. They all replied saying that you can do things like write a new language (e.g., Shen), perhaps by using Common Lisp as your implementation language.

Re: A difference between Haskell and Common Lisp

#143

Earlier quoted context omitted.

They can't be written in Lisp well, or at all. Strong typing with inference can't be bolted on. Monads that take advantage of this typing can't be bolted on. Changing Lisp to have lazy semantics across the board ain't gonna happen. You might be able to write a Haskell interpreter from scratch that interacts with the Lisp environment, but you can't feasibly transform Lisp itself.

Wrong. You can build an entire Haskell implementation as a thin, transparent layer on top of Lisp and then do anything Haskell can do.

My post literally says "you can build a Haskell interpreter which interacts with Lisp".

Re: A difference between Haskell and Common Lisp

#144
post #116

Earlier quoted context omitted.

They can't be written in Lisp well, or at all. Strong typing with inference can't be bolted on. Monads that take advantage of this typing can't be bolted on. Changing Lisp to have lazy semantics across the board ain't gonna happen. You might be able to write a Haskell interpreter from scratch that interacts with the Lisp environment, but you can't feasibly transform Lisp itself.

Nobody told Dr. Tarver[1]. He built a series of lisps with tight integration with the underlying Common Lisp platform featuring a strong typing system rooted in the propositions of Sequent Calculus[2][3]. Type delcarations are only on top level forms with all locals inferred. There seems to be work to improve this in Shen Professiona's new compiler. Shen offers tight integration with the underlying platform (although…

I guess I wasn't clear in my post.

Usually when people say "you can do X in Lisp", they mean that you can integrate a feature into the language.

Don't have list comprehensions? Write a macro.

Don't have "thrush" syntax? Write a macro.

Don't have lazy evaluation? Write a... err. You can't write a macro[1]. You can't write something which completely changes the entire calling semantics of the language. What you can do is make a little sub-language which uses different values and objects from Lisp, but you can't magically make the standard library support lazy evaluation.

Same with types and type inference (a la Haskell).

Same with many other things.

Of course, obviously, you can write a compiler that compiles to Common Lisp, or C, or Scheme, or COBOL. But writing a compiler -- while Lisp is good at that -- isn't really taking advantage of what it usually means for Lisp to be extensible.

[1] For those who are ready to call out the many "lazy" libraries in Common Lisp, perhaps even my own, you're missing the point. You can make a new version of DEFUN and a new version of FUNCALL. But that doesn't make REMOVE-IF, SUBSEQ, MAPCAR, LIST, CONS, etc. lazy. As such, many, if not most, of the benefits that laziness brings, don't get applied to the language at large.

Re: A difference between Haskell and Common Lisp

#145
post #140
post #63

Earlier quoted context omitted.

> Lisp functions and macros OTOH must be variadic to enable the homoiconicity of the language. That makes no sense at all. Homoiconicty is a syntactic concept, variadicity is a semantic concept. They have nothing to do with each other. The feature that enables Haskell's programming style is laziness, not currying. Lisp can be trivially curried, but it cannot be trivially made lazy, so idioms like "take 5 . filter p .…

> Homoiconicty is a syntactic concept, variadicity is a semantic concept. They have nothing to do with each other. It's far more difficult to define macros when you don't have variadicity. A large number of syntactic constructs you'd want to define would even be impossible.

> It's far more difficult to define macros when you don't have variadicity.

Why?

> A large number of syntactic constructs you'd want to define would even be impossible.

Like what?

Re: A difference between Haskell and Common Lisp

#146
post #118

Earlier quoted context omitted.

For being a pinnacle it is really unsatisfying. It tells you very little about how or what programs can be composed. It's either trial and error or reading man pages. In addition every program has to be written to take in anything as there are no constraints. Function composition via types is a much more satisfying take on this problem. It's too bad Unix is regarded as the holy grail of this technique when it barely…

Unix commands happily pass around binary streams of any format. The problem is, as you noticed, there is not schema, no uniform (let alone machine-readable) description of accepted / emitted formats. Composability is possible but not entirely trivial, often with a dose of `grep` / `sed` / `cut` between commands. It's also pretty hard to pass a function to a Unix command. Either your command supports its own syntax (g…

"It's also pretty hard to pass a function to a Unix command."

On this and a few other points, it would be interesting to allow a process to call out to the shell that it's running below ("... if any" being one of several issues with the idea).

Re: A difference between Haskell and Common Lisp

#147
post #145
post #140

Earlier quoted context omitted.

> Homoiconicty is a syntactic concept, variadicity is a semantic concept. They have nothing to do with each other. It's far more difficult to define macros when you don't have variadicity. A large number of syntactic constructs you'd want to define would even be impossible.

> It's far more difficult to define macros when you don't have variadicity. Why? > A large number of syntactic constructs you'd want to define would even be impossible. Like what?

Many functions and macros in Clojure rely on reducing variadic parameters using recursion, e.g.

  (defn max "Returns the greatest of the nums."
    ([x] x)
    ([x y] (. clojure.lang.Numbers (max x y)))
    ([x y & more] (reduce1 max (max x y) more)))
You'd be limited to 2 params if you didn't have variadicity. Some macros like switching, which in Clojure is called `condp`, would lose their elegant single-parens appearance if variadicity wasn't allowed.

Re: A difference between Haskell and Common Lisp

#148
post #119

Earlier quoted context omitted.

In chapter 4 of his book, Okasaki defines a type of both finite and infinite streams (which is really just the type of Haskell "lists"), and, in the remainder of the book, he only uses finite ones. A stream of infinite length, which you call "stream" without qualification, is what I call "a function on the natural numbers". (Well, up to isomorphism.)

Speaking of things that the Haskell type system lets you make explicit, the isomorphism between streams and functions from the natural numbers means that streams are "representable functors" in the jargon of category theory. [1] Knowing that a data type is representable allows you to immediately build a bunch of other interesting structures on the data type. [0] [0] http://covariant.me/notes/rep-functors.html [1] htt…

Nitpick on both links. They say `alpha . beta = id = beta . alpha`. This is wrong: `alpha . beta` composes to a different `id` from `beta . alpha`.

Re: A difference between Haskell and Common Lisp

#149
post #116

Earlier quoted context omitted.

Nobody told Dr. Tarver[1]. He built a series of lisps with tight integration with the underlying Common Lisp platform featuring a strong typing system rooted in the propositions of Sequent Calculus[2][3]. Type delcarations are only on top level forms with all locals inferred. There seems to be work to improve this in Shen Professiona's new compiler. Shen offers tight integration with the underlying platform (although…

I guess I wasn't clear in my post. Usually when people say "you can do X in Lisp", they mean that you can integrate a feature into the language. Don't have list comprehensions? Write a macro. Don't have "thrush" syntax? Write a macro. Don't have lazy evaluation? Write a... err. You can't write a macro[1]. You can't write something which completely changes the entire calling semantics of the language. What you can do…

What are macros if not custom compiler extensions?

Sure, Shen is enough of a compiler extension to be its own language, but I can call Common Lisp code from Shen and call Shen code from Common Lisp. Doing either isn't very different from calling a native function (calling Shen from Shen is similar to calling CL from Shen).

As far as [1], I don't really see this as an issue with CL. CL has not made the effort to rewrite its core in terms of generic functions. If this were to be done, drastically changing CL's behavior for random new types would be relatively painless. But the way that the current CL standard chose for its library and core functionality isn't to use generic functions everywhere. As such, it is expected that if you drastically change implementation, you end up with separate functions. I think this is a huge draw of something like Clojure/JVM with its interfaces/protocols as a base level over a far more mature system like CL/SBCL.

Re: A difference between Haskell and Common Lisp

#150
post #133
post #128

Earlier quoted context omitted.

> Well for me the value of using a monad to capture an effect is to be able to verify that I've sequenced that effect correctly at compile time. > I do prefer to have a type system which verifies the monad laws at compile time, and I do think that the stronger the enforcement around the monad system, the more worthwhile it becomes to manage a given effect explicitly. That's an advantage of having a type system, not o…

But effects do need to satisfy the laws if the "natural" way of writing them is to make sense, so I'd rather that were enforced (compare the confusing results one gets when using Set in a scala for/yield, because it doesn't obey the monad laws). Unless you're restricting the "interpreters" such that the implementation of a given action is necessarily monadic? (Have you seen the "freer monad, more extensible effects"…

> But effects do need to satisfy the laws if the "natural" way of writing them is to make sense, so I'd rather that were enforced (compare the confusing results one gets when using Set in a scala for/yield, because it doesn't obey the monad laws). Unless you're restricting the "interpreters" such that the implementation of a given action is necessarily monadic?

I haven't thought too much about it, but I believe that if you structure effects as continuations, then they are monadic by construction (though I may well be wrong) because the continuations themselves are monadic. But I got interested in continuations because I don't like Haskell's purity, and I wondered if there is an imperative construct with the same expressive power as the PFP monad, and it turns out that not only that there is one, but that it composes much better than monads.

> Have you seen the "freer monad, more extensible effects" paper? I think they end up in a similar place, though from the opposite direction - using a single structure typed by a (type-level) list of possible effects to represent an effectful operation, and then you supply an interpretation for each effect to run it

Yes, and it isn't a coincidence. Oleg Kiselyov started out trying to bring the composability of continuations to Haskell (he built at least one continuation library for OCaml). As I wrote in that blog post, that was an open question by Phil Wadler: whether monads could be made as composable as continuations, and Kiselyov showed that the could.

Post reply on HN