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!
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,
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
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
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
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
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!
:cd command doesn’t need the
To quit a GHCi session, use
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
: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.
First, we start with the absolute basics.
:– The colon by itself repeats the previous command.
:help– Gives you some help.
:! <cmd>– Allows you to use shell commands, such as
pwdin ghci. This is also useful to people building tools on top of GHCi.
:cd– Changes the directory that
ghcihas access to.
:load <file>– Loads the specified file into the GHCi session.
:main <args>– Runs a
mainwith some arguments.
:quit– Quit GHCi.
:reload– Does not take an argument. Reloads the current module, file, or project.
:set– This is used for many things; please see the article.
:set, but only affects commands typed at the GHCi prompt, not those loaded from a file.
:run– Similar to
Information about types and functions
Next you should become familiar with these commands for querying information about Haskell types and functions.
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
: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.
: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
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:
λ> max 5 _ <interactive>:76:7: error: • Found hole: _ :: a Where: ‘a’ is a rigid type variable bound by the inferred type of it :: (Ord a, Num a) => a ----------------------------------- ^^ at <interactive>:76:1-7 • In the second argument of ‘max’, namely ‘_’ In the expression: max 5 _ In an equation for ‘it’: it = max 5 _ ------------------------- ^^
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
it. But it’s not only GHCi that can pass
it as an argument to functions – you can, too!