Writing a REPL with Haskeline

A REPL(Read–eval–print loop) is a indispensable tool for a programming language.

In a REPL, the user enters one or more expressions (rather than an entire compilation unit), which are then evaluated, and the results displayed.

However, writing a good quality REPL is not trivial because it often requires complicated features. Some of the functionality provided by a REPL includes:

  • History of inputs and outputs.
  • Input editing and context specific completion over symbols, pathnames, class names and other objects.

In Haskell, we have the haskeline package which provides exactly these two features.

Haskeline provides a user interface for line input in command-line programs. This library is similar in purpose to readline, but since it is written in Haskell it is (hopefully) more easily used in other Haskell programs.

Haskeline provides a monad transformer, InputT. You can perform input and output with getInputLine and outputStrLn which are Unicode-aware. But you can also perform any IO action you want with liftIO.

I’ve just written a decent REPL for my scheme interpreter with Haskeline.

Writing a Scheme interpreter for fun

Writing a Scheme interpreter is a great way to learn Haskell. You can practice advanced Haskell techniques such as I/O, mutable state, dynamic typing, error handling, and parsing. There is a Wikibook named Write Yourself a Scheme in 48 Hours for this purpose.

I’ve just started writing a Scheme interpreter, HScheme to teach myself both Haskell and Scheme. The skeleton code is based on the Wikibook and I am working on the remaining features of R5RS Scheme standard. My first improvement to the interpreter was to support vectors.

Among the remaining features, Hygienic macro system is the most important feature I need to implement immediately because other parts of Scheme standard such as let-bindings and control flow features are defined in terms of macro. There are a whole collection of papers on macro implementation. I’ll write more on the implementation of Hygienic macros.

BTW, there is already a full-featured Scheme implementation in Haskell. Refer to Husk Scheme for details.