In your GHCi configurationGHC User’s Guide: The .ghci files (sometimes called your “dot ghci file”), you can write GHCi commands that will run automatically every time you start GHCi.

Config file locations

GHCi reads config files from the following locations:

  1. ./.ghci
  2. Depending on the OS:
    • Linux and macOS: $HOME/.ghc/ghci.conf
    • Windows: C:\Documents and Settings\<username>\Application Data/ghc/ghci.conf
  3. $HOME/.ghci

If more than one of these is present, then GHCi will run them all, in the order given above.

The first path ./.ghci is relative to the current directory, so it can be useful for project-specific options. The latter two are where you keep configuration that you will use all the time. You can choose to put your configuration in either location, according to your preference.

Customizing your prompt

By default, the GHCi prompt looks like this:This style of multiline syntax, introduced by :{ and closed by :}, is available in GHCi without any special settings.

Prelude> :{
Prelude| f :: Integer -> Integer
Prelude| f x = x + 1
Prelude| :}

It shows you what modules are imported, followed by > on the first line of each command, and | on any subsequent lines of a multi-line command. Often the module list ends up being obstrusively long, and so many people choose to set a different prompt. A popular choice is λ>. You can do this by setting the prompt and prompt-cont variables in your GHCi config:

:set prompt "\x03BB> "
:set prompt-cont " > "

Now your prompt will look like this:

λ> :{
 > f :: Integer -> Integer
 > f x = x + 1
 > :}

You can also use ANSI escape codesAn ANSI escape code, supported by most common terminals, is a sequence of characters beginning with the ASCII escape character. These codes do a variety of things; the ones we use here signify changing the text color. to apply color. For example, to turn the prompt purple:

:set prompt "\ESC[1;35m\x03BB> \ESC[m"
:set prompt-cont "\ESC[1;35m > \ESC[m"

Enabling language extensions

You can enable and disable GHC language extensions on the fly as you need them, but for extensions that you use very often, you may want to consider modifying your config to enable them by default.

For example, you might add something like this to your dot GHCi file, to enable these common basic extensions:See our recommended list of extensions for beginners.

:seti -XGADTSyntax
:seti -XGeneralizedNewtypeDeriving
:seti -XInstanceSigs
:seti -XLambdaCase
:seti -XPartialTypeSignatures
:seti -XScopedTypeVariables
:seti -XTypeApplications
:seti -XOverloadedStrings

You can use :set instead of :seti,The :set lesson will further discuss the difference between :set and :seti. but using :seti ensures that the extensions you have turned on here don’t affect any modules you’re trying to load, which may use a different set of extensions, or none at all.

Enabling GHCi options

You can similarly enable GHCi options via your configuration file if you want them on all the time. For example, the :set +t command is very useful for teaching; turning it on causes GHCi to automatically display the type of the last expression you evaluated, called it in GHCi.

λ> print "hello world"
"hello world"
it :: ()

λ> 5 + 5
it :: Num a => a

λ> x = 5 + 5
x :: Num a => a

Notice on the last line it gives the type for x instead of it; that’s because x hasn’t been evaluated yet, but x does have a type! If you then call x to evaluate it, the resulting type will be the same but will be given as the type of it.

λ> x
it :: Num a => a

Incidentally, you can use it as an argument to the next expression – it’s really handy if you’re ever inclined to use GHCi as a calculator!

λ> x = 5 + 5
x :: Num a => a

λ> x
it :: Num a => a

λ> it + 30
it :: Num a => a

λ> it + 20
it :: Num a => a

λ> it / 3
it :: Fractional a => a

Anything you can set with the :set command can be turned on by default each time you open GHCi by putting it into your GHCi configuration. That includes things like -fdefer-type-errors and -Wall!

Disabling GHCi config

If you want to start a clean, standard GHCi that is unaffected by any configuration files, start GHCi with the -ignore-dot-ghci flag.

$ ghci -ignore-dot-ghci

If you’re starting GHCi with Stack, it will look like this:

$ stack ghci --ghc-options -ignore-dot-ghci

Reading the source

If you’re curious about the details of how GHCi finds its config files, you can look at the source code for GHCi,The GHCi.UI module defines the loading of config files. which is located within the ghc git repository.

To obtain the OS-specific location, it uses the getAppUserDataDirectorygetAppUserDataDirectory function from the directoryThe directory package package, whose implementation (with some details omitted) looks like this:

getAppUserDataDirectory :: FilePath -> IO FilePath
getAppUserDataDirectory = getAppUserDataDirectoryInternal

getAppUserDataDirectoryInternal has a different implementation depending on what operating system the package is built for. On a Unix platform, it looks like this:

getAppUserDataDirectoryInternal appName =
  (\ home -> home <> ('/' : '.' : appName)) <$> getHomeDirectoryInternal

And on Windows, it looks like this:

getAppUserDataDirectoryInternal appName =
  (\ appData -> appData <> ('\\' : appName))
  <$> getXdgDirectoryInternal getHomeDirectoryInternal XdgData

You can try using this function yourself and see what it returns for your system:

$ stack repl --package directory
λ> import System.Directory

λ> getAppUserDataDirectory "xyz"

For historical reasons, GHCi does not follow the XDGXDG specifies a set of conventions for file paths. It has the advantage of allowing users to customize paths using environment variables, rather than forcing users to keep files in a particular location dictated by the program. Base Directory Specification, but it is recommended that you do so for new programs that you are writing. The directory package supports this as well: Use getXdgDirectorygetXdgDirectory instead of getAppUserDataDirectory.

λ> getXdgDirectory XdgConfig "xyz"

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