Using GHCi

GHCi, or GHC interactive, is the interactive shell (or REPL) for GHC Haskell. It’s a surprisingly featureful and useful tool, although many of its features are not actively taught to anyone, so they seem hidden and difficult to discover.

However, GHCi is invaluable in our day to day work, along with ghcid. One of the most common complaints about statically typed languages is that, while catching errors at compile time is nice and all, having to compile all the time forces a lengthy feedback loop. You change some things and then compile and then finally get back the errors telling you what to fix. It can seem like an unnecessary burden. The secret is neither we nor most of the Haskellers we know compile their code very often; instead, we interpret! You still get the compiler errors as if you compiled the code but on a much shorter – essentially immediate – time frame. We are constantly exploring what we can do with GHCi and finding new tools waiting there for us. The section of the GHC User Manual that covers using GHCi has more information than we’re going to explain here – but also less, in some cases, as is often the case with technical documentation. This series will show off how we, a couple of experienced and mostly happy Haskellers, use GHCi, rather than trying to be absolutely comprehensive. Since we use it a lot, it will end up covering more than most people probably suspected was there to cover.

This is the starting point of a series of articles that explain some of the features GHCi provides. We’ll start here with some basic information about GHCi; from here, the GHCi articles are linked as a series, but you can feel free to jump around by going to the tooling page as well. And if you want to start off by customizing your GHCi prompt so that you, too, have a lambda prompt, you can start by reading about GHCi configuration if you like. We won’t lie: it was also one of the first things we did when we started using Haskell!

Invoking GHCi

Assuming you already have a working installation of GHC on your machine, you should be able to open a GHCi session by typing ghci on the command line from any directory that can access GHC. Both of the major build tools, cabal and stack, have their own commands to open project-aware REPLs, but using those will not be our focus here. Further documentation is available here for cabal users and here for stack users. One benefit of using these is that opening a GHCi session from within a project directory using, e.g., stack repl, may load your Main module automatically and also make the GHCi session aware of the project’s dependencies.

Haskell expressions can then be typed directly at the prompt and immediately evaluated.

GHCi will interpret the line as a complete expression. If you wish to enter multi-line expressions, you can do so with some special syntax.

Invoking GHCi with options

You can open GHCi with a file loaded from the command line by passing the filename as an argument. For example, this command loads the file fractal.hs into a new GHCi session:

If that module has dependencies other than the base library, though, they won’t be loaded automatically. We’ll cover bringing those into scope in a separate section, below.

You can also open GHCi with a language extension, for example, already turned on. For example,

But if you pass it the -XOverloadedStrings flag, then that language extension will be enabled for that session.

A great number of other GHC flags can be passed as arguments to ghci in this fashion. For the most part, we will cover those as they come up in other contexts, rather than attempting to list them all here.

Your GHCi configuration, if you have one, will be loaded by default when you invoke ghci. You can disable that with a flag:

GHCi with packages

There are a few ways to bring modules and packages into scope in GHCi. One is using stack or cabal to open a project-aware REPL, which usually works well to bring the appropriate dependencies into scope. However, there are a few other options.

You can import modules directly in GHCi using import, just as you do at the top of a file if your GHCi is already aware of the package the module comes from.

All modules in base are fair game for importing, as are modules in a project-aware GHCi session or a GHCi session that has been invoked with the -package flag, thus loading the package into the session.

All the same import syntax is available for this, such as hiding and qualified.

The base package is always loaded by default into a GHCi session (as is the Prelude module, unless you have disabled that), but that’s not, of course, the case for many packages. However, your GHC installation came with a few packages that are available but not automatically loaded into new GHCi sessions. You can find out what you have available by running

on the command line. You should see a list of all the packages that are installed and available. Modules from any of those listed packages can be directly imported, just as if they were in base. So, assuming your list includes containers, you can type import Data.Map or the like directly into your GHCi session, regardless of whether it’s one of your project’s dependencies – or if you even have a project going.

If you are using a stack or cabal REPL, then there may be many more packages in their local package lists that are available to new GHCi sessions. If you have previously opened a GHCi session with something like

then stack will have installed QuickCheck and, if in the future you open a stack repl session but forget to pass the --package flag and then suddenly you realize you want to make QuickCheck available in this GHCi session, you can :set -package within GHCi to bring it into scope:

It’s really handy not to have to restart a GHCi session just to load a package you use frequently!

List of GHCi commands

First let’s start with a couple of basics: you can use the up-arrow, down-arrow, and tab-complete in GHCi, so if you are already comfortable with these from your bash shell or what have you, you’ll enjoy this.

Furthermore, if you are in a GHCi session, shell commands can be made available using the :! GHCi command. For example, let’s say we’ve forgotten what directory we’re in and what files are in this directory, but we don’t want to quit GHCi to find out. No problem!

Notice the :cd command doesn’t need the :!.

To quit a GHCi session, use :quit or :q.

GHCi commands all start with a colon (except import). They may all be abbreviated to just their first letter; however, if there is more than one command that starts with the same letter, such as :main and :module, it will default to reading that as whichever is more commonly used. When in doubt, type it out.

Here is an exhaustive, annotated list of GHCi commands, somewhat divided by task. Many of these will be covered in more detail in their own articles.

Basics

First, we start with the absolute basics.

  • : – The colon by itself repeats the previous command.
  • :? or :help – Gives you some help.
  • :! <cmd> – Allows you to use shell commands, such as pwd in ghci. This is also useful to people building tools on top of GHCi.
  • :cd – Changes the directory that ghci has access to.
  • :load <file> – Loads the specified file into the GHCi session.
  • :main <args> – Runs a main with some arguments.
  • :quit – Quit GHCi.
  • :reload – Does not take an argument. Reloads the current module or file.
  • :set – This is used for many things; please see the article.
  • :seti – Like :set, but only affects commands typed at the GHCi prompt, not those loaded from a file.
  • :run – Similar to :main.
  • :unset – Undoes :set.

Information about types and functions

Next you should become familiar with these commands for querying information about Haskell types and functions.

  • :doc <arg> – (new, unstable) Show the documentation for a Haskell type, etc., right in the REPL.
  • :info – Queries information about a type, typeclass, value, function, or operator.
  • :kind – Queries the kind of a type.
  • :type – Queries the type of a value or function.
  • :type-at

Scope and availability

This set of commands is used for finding information about what’s in scope or changing what is in scope.

  • :add – Adds a module to the current target set and reloads.
  • :all-types – Lists all types for expressions and local bindings that are currently loaded.
  • :browse – Gives a list of the contents of a module (the module need not be imported).
  • :issafe <module> – Tells you the Safe Haskell information for a module (the current one if none is specified).
  • :module – Imports or de-imports modules. Can be used to expose an entire module, rather than only its exports.
  • :show – Followed by modules, it lists the modules that are currently in scope; followed by imports, it lists the imports that are in scope.

Debugging and evaluation

And here is a list of commands that are part of GHCi’s built-in debugging tools or useful for examining the evaluation of Haskell expressions.

  • :abandon – Abandons the current evaulation when stopped at a breakpoint.
  • :back <n> – Travel back <n> steps in the history. <n> is 1 when unspecified.
  • :break – Used to set a breakpoint.
  • :continue – Used to continue evaluation after a breakpoint.
  • :delete – Takes an argument: a number or *. Deletes the specified number of breakpoints. If given *, deletes all breakpoints.
  • :force <id> – Forces the printing of the identifier passed to it as an argument, forcing all the thunks along the way.
  • :forward <n> – Moves forward <n> steps in the history. <n> is 1 when unspecified.
  • :history <n> – Displays the history of the evaluation. If given a numeric argument, it displays that number of steps; otherwise, the default is 20.
  • :list <id> – Lists the source code around the definition of the identifier or the current breakpoint.
  • :print <id> – Prints a value without forcing its evaluation.
  • :sprint – Prints what has been evaluated so far while showing thunks with an underscore. Helpful for understanding laziness.
  • :step – Enables single-stepping through program evaluation. There is also :steplocal and :stepmodule.
  • :trace <expr> – Traces evaluation of the expression and logs it for later inspection.

Advanced, less common

Most of these are not commonly used unless you are building something on top of GHCi or working on editor or IDE integration.

  • :cmd
  • :complete
  • :ctags – Important for shaving certain Vi-style yaks.
  • :def – Takes arguments. Allows you to define custom GHCi commands and macros.
  • :edit <file> – Opens an editor to permit editing of a file, either the one passed to it as an argument or the currently loaded one.
  • :etags – This one is for the Emacs-flavored yaks.
  • :loc-at – Used for IDE and editor integration.
  • :script <file> – When given a filename as an argument, it executes the lines of code in that file as a series of GHCi commands.
  • :undef – Undoes whatever you did with :def.
  • :uses

What is it

GHCi assigns the name it to the last-evaluated expression. If you aren’t using :set +t to automatically display types for expressions entered into or evaluated in GHCi, then you might not notice it until you see an error message that mentions it such as this one:

It isn’t always important or useful to recognize that GHCi has named the expression, but there’s at least one interesting thing about it that you may find useful. Here’s a clue:

GHCi is always implicitly running the print function to display expressions and values on the screen; print takes an argument, and for GHCi, that argument is often it. But it’s not only GHCi that can pass it as an argument to functions – you can, too!

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.