Hacker News new | comments | show | ask | jobs | submit login
Writing A Lisp Interpreter In Haskell (defmacro.org)
116 points by llambda on Nov 9, 2012 | hide | past | web | favorite | 31 comments

Not sure if you've seen this one:


I haven't done it, but I hear its excellent.

This was how I learned Haskell. I rather liked it.

That said, looking back, I'm not sure it encourages the best coding style or the best idioms. It's perfect for getting your head around the paradigm though!

I'm currently writing an analogous tutorial for implementing Prolog in Haskell, but it's on a bit of a hiatus thanks to some school and research related deadlines coming up. Hopefully people are interested in something like that :).

Interestingly enough, the Prolog interpreter is actually shorter than the simple Scheme one--largely because we can take advantage of the list monad for the backtracking. I think it's still a very cool exercise.

I would be very interested in seeing a tutorial detailing how to implement Prolog in Haskell!

Not really a tutorial and not really Prolog, but here's an interpreter for a logic programming language written in Haskell: https://github.com/rikusalminen/slolog

I wrote it as a project work in an Artificial Intelligence class. It very closely resembles the logic programming language implemented in "Structure and Interpretation of Computer Programs".

I'm sorry there isn't any documentation for it.

Here's a little example of what it looks like, from examples/royalfamily.slo:

(siblings ?x ?y) <- (parent ?x ?parent) & (parent ?y ?parent)

(grandparent ?x ?y) <- (parent ?x ?z) & (parent ?z ?y)

(cousins ?x ?y) <- (grandparent ?x ?gp) & (grandparent ?y ?gp) & !(siblings ?x ?y)

That sounds awesome! I'd be very interested in that prolog interpreter tutorial.

It would be even more excellent if people for a change wrote more _in_ scheme instead of _a_ scheme.

Why write a program that gets your job done when you can just as easily write a language that makes writing that program trivial?

(I'm only being partly tongue-in-cheek - that's mentality behind idiomatic Lisp).

It would be the equivalent to writing Java on top of Haskell. You wouldn't creat Java, you would be creating _a_ Java.

"Scheme" has many different dialects as well. Racket is _a_ Scheme, Edwin interprets MIT's version of Scheme, then there is Gambit Scheme. There are certainly other Schemes, and the implementation of Scheme on Haskell isn't going to be the same as the other dialects listed here.

There are quite a few examples of Prolog-to-Lisp interpreters, but no one would argue that any of these _are_ Prolog.

I would say this tutorial is an excellent one to read through when you are first learning Haskell, and then return to it later when you have a better understanding of the language. Some important concepts are glazed over, and you will almost certainly not understand what is going on the first time you read the tutorial.

Once you are comfortable with Haskell the code makes much more sense and is a great starting point for writing an interpreter of your own.

Note that this is from 2006. "There hasn't been much Haskell-related work in [web applications]" is false, now.

Very cool read, though.

For a practical version for production usage, I've found husk-scheme (https://github.com/justinethier/husk-scheme) quite good.

I like Husk very much. I used its TCO/K approach for my own little hobby Lisp. Great fun.

Interesting that despite having what looks to me like Haskell and CL expertise, Slava's RethinkDB (various article describe as a "founder") seems to be written in C++.

What do Haskell or CL implementation lack to be competitive with good old C++ there?

When writing a database, performance is extremely important. Languages like C++ give you manual control of the computer's resources, which means you can count on predictable performance and memory management. Why is this important? All of your database code must be written with the performance characteristics of your data structures in mind. You need to know how long certain operations or memory swaps will take so that you can optimize data throughput.

While CL and Haskell can be extremely fast and even outperform C++ in certain situations, the lack of manual resource management makes them ill suited to writing a database system. There are few, if any, applications where this matters so much.

So what unpredictable performance characteristics do CL & Haskell exhibit, that languages like Java or Erlang do not?

Consider Neo4J, Cassandra, CouchDB, Riak, Voldemort, all major players in the current NoSQL world. All use Java & Erlang.

Just how much computation does your database need to do, unless it's some special in-memory database like Redis? If you have your data on ordinary disks, you'll spend most of the time waiting for them.

Space leaks are a big problem in Haskell that many neophytes and experts alike get massively caught up in—laziness is a double-edged sword.

Why can't we have the expressiveness of CL or Haskell with the performance of C++?

We can, theoretically. We just haven't yet developed algorithms that are clever enough to make the correct optimizations to code in enough of the cases where such optimizations are possible. There are patterns in our code that we humans can write out when we write our code in C++, but that we haven't yet formalized and implemented for the computer to do.

We do, its called the D programming language.

  map (head &&& length) . sort . group
  filterM (const [True, False])
Can you show how you implement these in D?

If you want, I can explain these or give other examples of expressiveness I don't think you'll find in D.

Links explaining these Haskell code snippets:

http://stackoverflow.com/a/10410997/578288 – the `map` snippet converts a flat list into a multiset represented as a list of `(count, element)` tuples

http://stackoverflow.com/a/5378799/578288 – the `filterM` snippet returns the powerset of its list argument (http://en.wikipedia.org/wiki/Power_set)

That is one of the best implementations of powerset I've seen in a while. Thank you for that!

I think you mean group . sort

Oops, quick-typing on my phone can have problematic results :-)

That feels a little surprising to me. Last time I looked at D it was nowhere close to CL or Haskell in expressiveness? (It was certainly better than C and less complicated than C++).

Has there been significant improvements in the past couple of years?

There really has. D 1.0 has 20 days of life left, and D 2.0 is really amazing. It has the C++ idea of "it's only there if you want it" but taken to an amazing degree. Yes, it's a little more verbose than most FP languages, but honestly, if you're interested in verbosity, go use J or Coke.

The thing I like about D is that there's no surprises, everything works the way you'd expect it to. You can guess at what code should look like, and chances are it'll work.

Can you detail, or point to background info? There've been type system debates between proponents of Haskell, ocaml, SML, scala, and F#, i've never seen a D to Haskell comparison, and I've never seen D mentioned as a "free theorems" language. Maybe in this vid:


Here's a scala to haskell


For example, the RethinkDB coroutine engine is written in assembly. We couldn't come close to the same level of control in any other language. For systems programming C and/or C++ are still kings.

Hopefully Rust will soon become a viable alternative.

This is, of course, a narcissistic nonsense.

A primitive arithmetic interpreter and the set primitive (why?) is not even close to what Lisp is.

Lisp is not just a prefix notation with parenthesis. It begins with the notion that code is data - the list structure and that everything is a symbol, a reference and that a value has a type, not a variable, which, together, gives us macros for free.

An implementation of a prefix-notation calculator? Well. It is less than one screen of Scheme code, and is a part of one lecture of freshman's CS61A course.

btw, people who have seen Scheme interpreter from SICP and capable to appreciate its beauty and elegance (structure, clarity, compactness) would never try to do something like that.)

Parenthetically speaking, are you aware of the issue with your parentheses?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact