Live data from Hacker News

A difference between Haskell and Common Lisp

chrisdone.com

131–140 of 203 posts

Re: A difference between Haskell and Common Lisp

#131

The main difference is: it is trivial to build an efficient Haskell implementation on top of Common Lisp, keeping interoperability with the rest of the system. And it is impossible to do it the other way around, to build a Lisp on top of Haskell.

https://wiki.haskell.org/Haskell_Lisp

I'm talking about an efficient implementation with a full interoperability with the host. Interpreters and standalone compilers do not count.

Re: A difference between Haskell and Common Lisp

#132
> In Lisp a procedure tends to accept many options which configure its behaviour. This is known as monolithism, or to make procedures like a kitchen-sink, or a Swiss-army knife.

This is the case in some areas of the Common Lisp language; it is not true of the Lisp, as a family of dialects.

There are plenty of examples of Lisp functions or operators that just do one thing: `cons`, `car`, the `lambda` macro operator.

   ;; CL
   (remove-if-not #'p xs :count 5 :start 3)

   ;; Haskell
   take 5 . filter p . drop 3

   ;; TXR Lisp: a dialect with ties to CL:
   (take 5 [keep-if p (drop 3 list)])

   ;; Compose the functions using opip macro
   ;; (result is a function object):
   (opip (drop 3) (keep-if p) (take 5))
TXR Lisp's library functions don't have the :count, :start and whatnot. In fact, there are no keyword parameters, only optionals. If you want to default an optional on the left and specify a value of one on the right, you can pass the colon keyword to explicitly default:

   (defun opt (a : (b 1) (c 2)) ;; two optional args
     )

   (opt 4 : 5)  ;; b takes 1, c takes 5.
The colon is just the symbol whose name is the empty string "", in the keyword package. It makes for nice sugar and has a couple of uses in the language. Note how in the defun it separates required args from optionals.

(Anyone else cringe at "UNIX philosophy"; how silly! This is the Unix philosophy: let's reduce everything to a string in between processing stages and parse it all over again, with simplifying assumptions that it always has exactly the format we are looking for without actually validating it.)

Re: A difference between Haskell and Common Lisp

#133
post #128
post #76

Earlier quoted context omitted.

> Well, extremely low-overhead of just about anything is certainly achievable with modern JITs[1]. Can't read twitter where I am, but to be clear I was primarily thinking of the code-readability overhead. > Why is that necessary? You might as well presuppose the necessity of types :) 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 compil…

> 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" 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)

Re: A difference between Haskell and Common Lisp

#134

Earlier quoted context omitted.

unix commands may not be the pinnacle of minimalism, but the most important thing UNIX taught is about composability. Yes, I did recognize the irony of the fact that the common lisp example was much more like a unix command line than the haskell example, but if you're talking about composing (relatively) small commands, unix is still a pretty good comparison.

I can't find anything to support that in the IEEE POSIX ISO spec from the Austin WG, but the GNU toolset definitely supports your assertion. I think it's important to recognize that POSIX is not SCO UNIX (UNIX(tm) is effectively a trademark and nothing more at this point) which is not GNU/Linux which is not LSB(Linux Standard Base). POSIX itself is a huge PCB of bodge-wires due to legacy compliance. On the upside for…

>POSIX is not SCO UNIX (UNIX(tm) is effectively a trademark and nothing more at this point)

UNIX is more than just a trademark, more importantly it is the test suite you have to pass to be allowed to use the trademark. And the trademark doesn't belong to SCO, it belongs to The Open Group, a not-for-profit industry consortium (successor to X/Open and the Open Software Foundation.)

Does it matter that much? I'm sure it makes it easier to port a package to a certified UNIX, since you know a certain collection of APIs must be there (putting aside the fact that some parts of the UNIX standard are optional)

Re: A difference between Haskell and Common Lisp

#135

> In Lisp a procedure tends to accept many options which configure its behaviour. This is known as monolithism, or to make procedures like a kitchen-sink, or a Swiss-army knife. This is the case in some areas of the Common Lisp language; it is not true of the Lisp, as a family of dialects. There are plenty of examples of Lisp functions or operators that just do one thing: `cons`, `car`, the `lambda` macro operator. ;…

That's the JWZ perspective, but if you add strong typing you can basically turn the "string" into "SomeType" and process records like that. If you look at languages with a |> operator they often act like that.

Re: A difference between Haskell and Common Lisp

#136

Earlier quoted context omitted.

unix commands may not be the pinnacle of minimalism, but the most important thing UNIX taught is about composability. Yes, I did recognize the irony of the fact that the common lisp example was much more like a unix command line than the haskell example, but if you're talking about composing (relatively) small commands, unix is still a pretty good comparison.

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…

I don't know if the problem is text as much as it is the pissweak type system that the whole POSIX environment supports. The other big beef I have is with the total donkey circus that are the interfaces to the various tools. They're ridden with terrible special cases and mutually contradictory parameters and only make sense to poor bastards like myself who've spent years using them to build ad-hoc programs.

Re: A difference between Haskell and Common Lisp

#137

Earlier quoted context omitted.

unix commands may not be the pinnacle of minimalism, but the most important thing UNIX taught is about composability. Yes, I did recognize the irony of the fact that the common lisp example was much more like a unix command line than the haskell example, but if you're talking about composing (relatively) small commands, unix is still a pretty good comparison.

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…

People seem to have forgotten that when Perl evolved from being a better AWK to the paradigm example of the modern "scripting language", Larry Wall explicitly described this as a rejection of the Unix small-tools philosophy. http://www.linux-mag.com/id/322/ ("But Perl was actually much more countercultural than you might think. It was intended to subvert the Unix philosophy. More specifically, it was intended to subvert that part of Unix philosophy that said that every tool should do only one thing and do that one thing well.") http://www.wall.org/~larry/pm.html The fact that getting things done with a Perlesque scripting language is now seen as the height of purist Unix propriety only shows how far gone the original Unix ideal now is. But moving to the scripting-glue model doesn't really get rid of small tools that endeavour to do one thing well, it just reimplements them inside the scripting-language universe as functions/objects, though with a more expressive and less burdensome common language that makes it easier for them to stay small while being correct and effective. The more expressive their shared language, the smaller a set of tools can be.

> Text just isn't a great medium for IPC.

Yes, in retrospect Unix's determination to know about nothing but binary or plaintext blobs and streams looks like an adolescent rebellion against the (apparently - I haven't used them) clunky record structures of '60s operating systems.

Re: A difference between Haskell and Common Lisp

#138
post #114

Earlier quoted context omitted.

UNIX may have been about small commands ("cat -v", anybody?), but its most important property is COMPOSABILITY. You could use small programs to build larger programs, allowing you to do things by gluing together code that you would previously have to write new programs to do. It made this very easy, and you could also do it from within C, so it wasn't an either/or situation. This is something your namesake system cou…

That was already available in Xerox PARC systems, by making use of function call composition in Interlisp-D REPL, Builders in Smalltalk transcript or live debugger in Mesa/Cedar. The UNIX composition is only a novelty for those that never saw other OSes that surfaced at the same time. After all UNIX just adopted the idea from MULTICS.

"The UNIX composition is only a novelty for those that never saw other OSes that surfaced at the same time. After all UNIX just adopted the idea from MULTICS."

One could certainly chain programs through intermediate files. My understanding has it that pipelines were new in Unix, and Wikipedia agrees: "The pipeline concept was invented by Douglas McIlroy and first described in the man pages of Version 3 Unix."

Re: A difference between Haskell and Common Lisp

#139
post #125
post #14

Haskell has strong typing and lazy evaluation, which makes it easy for functions to take only one argument at a time. Although a function could take a tuple parameter, it's usually rewritten to take each component of the tuple as a separate parameter, which makes the strong typing and built-in currying simple, higher structures like monads possible, and a syntax to suit this style. Lisp functions and macros OTOH must…

You can have currying in a dynamically-typed, strictly evaluated language.

But when that language has variadic parameters, you must explicitly invoke the currying to distinguish it from a normal function call that uses up all the variadic parameters (just as you can't specify different types for the variadic parameters). In a language where each function has only one parameter, the currying can be implicit (just as all parameters defined in the program can be statically typed).

Re: A difference between Haskell and Common Lisp

#140
post #63
post #14

Haskell has strong typing and lazy evaluation, which makes it easy for functions to take only one argument at a time. Although a function could take a tuple parameter, it's usually rewritten to take each component of the tuple as a separate parameter, which makes the strong typing and built-in currying simple, higher structures like monads possible, and a syntax to suit this style. Lisp functions and macros OTOH must…

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

Post reply on HN