We’ll start with a basic overview to see what working with GHCi is like: how to run it, how to use commands, and how to read its output.
Starting 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.
$ ghci
Haskell expressions can then be typed directly at the prompt and immediately evaluated.
λ> 5 + 5
10
λ> "hello" ++ " world"
"hello world"
λ> let x = 5+5 ; y = 7 in (x * y)
70
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.
λ> :{
> let x = 5+5; y = 7
> in
> (x * y)
> :}
70
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:
$ ghci fractal.hs
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,
$ ghci
<elided opening text>
λ> :type "julie"
"julie" :: [Char]
But if you pass it the -XOverloadedStrings
flag, then that language extension will be enabled for that session.
$ ghci -XOverloadedStrings
<elided opening text>
λ> :type "julie"
"julie" :: Data.String.IsString p => p
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 -ignore-dot-ghci
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.
λ> :type bool
<interactive>:1:1: error: Variable not in scope: bool
λ> import Data.Bool
λ> :type bool
bool :: a -> a -> Bool -> a
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
$ ghc-pkg list
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
$ stack repl --package QuickCheck
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:
λ> :type property
<interactive>:1:1: error: Variable not in scope: property
λ> :set -package QuickCheck
package flags have changed, resetting and loading new packages...
λ> import Test.QuickCheck
λ> :type property
property :: Testable prop => prop -> Property
It’s really handy not to have to restart a GHCi session just to load a package you use frequently!
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!
λ> :! pwd
/home/jmo
λ> :cd /home/jmo/haskell-projects
λ> :! ls
emily fractal-sets haskell-fractal life shu-thing web-lesson4
Notice the :cd
command doesn’t need the :!
.
To quit a GHCi session, use :quit
or :q
.
GHCi commandsMuch of this course will be about GHCi commands. List of commands gives an overview of all of them, and several other lessons elaborate on specific commands of particular importance. 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.
You can type :?
for a complete listing of the GHCi commands.
What is it
GHCi assigns the name it
to the last-evaluated expression. If you aren’t using :set +t
We will see :set +t
and other uses of :set
later in the page on the GHCi :set command. 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:
λ> max 5
<interactive>:75:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
---------------------------------------------- ^^^^^ ^^
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!
λ> sum [1..500]
125250
λ> it / 15
8350.0
λ> it * 2
16700.0