Chapter 2. Getting Started

Table of Contents

Your Haskell environment
Installing GHC on your platform
Windows
Mac OS X
Ubuntu and Debian Linux
Fedora Linux
Getting started with ghci, the interpreter
Command line editing
Basic interaction: using ghci as a calculator
Simple arithmetic
An arithmetic quirk: writing negative numbers
Undefined values, and introducing variables
Comparison and boolean operators
Rational numbers, the Haskell prelude, and modules
Aside: the faces of exponentiation
Don't sweat those error messages
Text, strings and lists
First steps with types
Exercises
Conclusion

Your Haskell environment

There's a number of Haskell implementations available, of which two are in wide use. Hugs 98 is an interpreter that is primarily used for teaching. For real applications, the Glasgow Haskell Compiler, or GHC as it's usually known, is much more popular.

GHC has two complementary components: ghc, a compiler that generates native code, and ghci, an interpreter that can run either interactively or in “batch” mode.

[Note]Note

When we discuss the package as a whole, we'll refer to it as GHC. If we're talking about one or another command, we'll mention either ghc or ghci.

In this book, we assume that you're using at least version 6.6.1 of GHC. To obtain a copy of GHC for your platform, visit the GHC download page, and look for the list of binary packages. If you're using Windows or Mac OS X, these binary packages are the best ones to use.

Many Linux distributions, and BSD and other Unix variants, make pre-packaged versions of GHC available. Because they are built specifically for each environment, these packages are less hassle to use than the generic binary packages. You can find a list of such packages at the GHC distribution packages page.

Installing GHC on your platform

We are providing the instructions below based on our experience installing GHC in mid-2007. Installation instructions inevitably become dated quickly; please bear this in mind as you read.

Because GHC runs on a large number of platforms, we've focused on a handful of the most popular.

Windows

The prebuilt binary packages of GHC should work on versions of Windows as old as ME, and on all newer versions (NT, 2000, XP, and Vista). We have installed GHC 6.6.1 under Windows XP Service Pack 2; here are the steps we followed.

[Note]Note

On Windows, GHC requires almost 340MB of disk space.

Our first step is to visit the GHC download page, and follow the link to the current stable release. Scroll down to the section entitled “Binary packages”, and then again to the subsection for Windows. Download the installer; in our case, it's named ghc-6.6.1-i386-windows.exe.

After the installer has downloaded, double-clicking on it starts the installation process. This simply involves stepping through a normal Windows installer wizard.

Once the installer has finished, the Start Menu's “All Programs” submenu should have a GHC folder, inside of which you'll find an icon that you can double-click on to run ghci.

Clicking on the ghci icon brings up a normal Windows console window, running ghci.

[Note]Note

The GHC installer automatically modifies your user account's PATH environment variable so that commands like ghc will be present in the command shell's search path (i.e. you can type a GHC command name without typing its complete path). This change will not take effect until you log out and back in again.

Mac OS X

Installing GHC on Mac OS X takes several steps, as GHC does not yet have a standard OS X installer. We have installed GHC 6.6.1 under Mac OS X 10.4, on an Intel-based MacBook. We're not regular Mac users, and had never tried installing GHC on OS X before, and everything worked for us on the first try, so take heart if these instructions seem daunting. The process is neither difficult nor especially time-consuming.

Our first step is to visit the GHC download page, and follow the link to the current stable release. Scroll down to the section entitled “Binary packages”, and then again to the subsection for Mac OS X. There are four components to download, all of which are necessary.

  • Apple's Xcode development software. This provides compiler toolchain support that GHC needs.

  • The GNUreadline framework provides flexible command line editing.

  • The GMP framework is required for arbitrary-precision integer support.

  • The GHC package itself. This will not work unless both of the preceding frameworks are installed.

The Xcode software installer may have come bundled on a DVD with your Mac. If not (or you can't find it), you can download it from Apple and install it. Once you've finished installing Xcode, continue on to download the remaining three packages.

After these downloads complete, you'll have three archive icons on your desktop.

Double click on each one to unpack it, giving you three folders.

Open a Finder window with command-n. In the left sidebar, click on your system's main hard disk icon (often named “Macintosh HD”). In the main portion of the window, double click on System to open that folder, then on Library. Select the GMP.framework and GNUreadline.framework folders on your desktop, and drag them onto the Frameworks folder in the Finder window that is visiting /System/Library. If the Finder refuses to install them because you don't have permission, it will probably display an “Authenticate” button in the alert it displays. Click it, enter your password, and installation can proceed.

With the prerequisites in place, you can turn to installing GHC. You'll need to open a Terminal window (you can find it in /Applications/Utilities).

[Note]Note

Since most of your interactions with GHC will be through a Terminal window, this might be a good time to add the Terminal application to your dock, if you haven't already done so.

Inside the Terminal window, change directory to Desktop/ghc-6.6.1, and run ./configure to set up the command line installer. This configures GHC to install to /usr/local. When the configure script finishes, run sudo make install, and type your password when you are prompted for it.

The installation process should take a minute or two. If you don't already have /usr/local/bin in your shell's search path, add it.

Finally, you should be able to successfully run the ghci command from your shell prompt.

Ubuntu and Debian Linux

FIXME: actual content.

Fedora Linux

GHC is packaged for Fedora. From a shell, all you need to do is run sudo yum -y install ghc ghc-doc ghc661-prof. The base package, containing the ghc and ghci commands and libraries, is ghc. The ghc-doc package contains the GHC user guide, and command and library documentation. The ghc661-prof package contains profiling-capable versions of the standard libraries (note: its version number may have changed by the time you read this).

Once installation has finished, you should be able to run ghci from the shell immediately. You won't need to change your shell's search path, or set any environment variables.

Getting started with ghci, the interpreter

The interactive interpreter for GHC is a program named ghci. It lets you enter and evaluate Haskell expressions, and explore modules and type information.

When we run ghci, it displays a startup banner, followed by a Prelude> prompt.

$ ghci
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
Prelude>

$ ghci
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
Prelude>
[Note]Note

The prompt displayed by ghci changes depending on what we're doing, and can often grow long enough to leave little visual room on a single line for our input. For brevity, we have replaced ghci's default prompts throughout this book with the prompt string ghci>.

Command line editing

On most systems, ghci has some amount of command line editing ability. On Unix-like systems, it uses the GNU readline library, which is powerful and customisable. On Windows, ghci's command line editing capabilities are provided by the doskey command.

If you haven't used command line editing before, it's a huge time saver. The basics are common to both Unix-like and Windows systems. Pressing the up arrow key on your keyboard recalls the last line of input you entered; pressing up repeatedly cycles through earlier lines of input. You can use the left and right arrow keys to move around inside a line of input.

Just knowing this much will save you a lot of repeated typing. If you want to learn more about command line editing on your system, consult the readline or doskey documentation.

Basic interaction: using ghci as a calculator

Where some people might run a calculator program, I often drop into ghci to perform simple calculations. Using it this way serves as a good way to become familiar with ghci itself, and with the basics of Haskell expressions.

Simple arithmetic

We can immediately start typing expressions, to see what ghci will do with them. Basic arithmetic works as we'd expect.

ghci> 2 + 2
4
ghci> 31337 * 101
3165037
ghci> 7/2
3.5
ghci> 2 + 2
4
ghci> 31337 * 101
3165037
ghci> 7/2
3.5

As the expressions above imply, Haskell has a notion of integers and floating point numbers. In fact, it allows us to use arbitrarily large integers. Here, the (^) is the exponentiation operator.

ghci> 31337 ^ 15
27596961266048865189478071639245914618921288733595362747095073723993
ghci> 31337 ^ 15
27596961266048865189478071639245914618921288733595362747095073723993

Like other languages that use infix notation to write mathematical expressions, Haskell has a notion of operator precedence. This allows us to get rid of a few parentheses. For example, the multiplication operator has a higher precedence than the addition operator, so Haskell treats the two following expressions as equivalent.

ghci> (4 * 4) + 1
17
ghci> 4 * 4 + 1
17
ghci> (4 * 4) + 1
17
ghci> 4 * 4 + 1
17
[Note]Note

As in other languages, it's often better to leave at least some parentheses in place, even when Haskell allows us to omit them. Their presence can help future readers (including ourselves) to understand what we intended.

Even more importantly, complex expressions that rely on operator precedence are notorious sources of bugs. A compiler and a human can easily end up with different notions of what a long, parenthesis-free expression is supposed to do.

An arithmetic quirk: writing negative numbers

Haskell presents us with one peculiarity in how we must write numbers: it's often necessary to enclose a negative number in parentheses. This affects us as soon as we move past writing the simplest of expressions.

ghci> -3
-3
ghci> 2 + -3

<interactive>:1:0:
    precedence parsing error
	cannot mix `(+)' [infixl 6] and prefix `-' [infixl 6] in the same infix expression
ghci> 2 + (-3)
-1
ghci> -3
-3
ghci> 2 + -3

<interactive>:1:0:
    precedence parsing error
	cannot mix `(+)' [infixl 6] and prefix `-' [infixl 6] in the same infix expression
ghci> 2 + (-3)
-1

Later on, we'll be seeing how Haskell lets us devise entirely new infix operators. Now that we've been forewarned, the following may not prove too surprising.

Most of the time, we can omit whitespace from expressions, and Haskell will parse them as we intended. But not always. Here's an expression that works:

ghci> 2+3
5
ghci> 2+3
5

And here's one that similar to the problematic negative number example above, but results in a different error message.

ghci> 2+-3

<interactive>:1:1: Not in scope: `+-'
ghci> 2+-3

<interactive>:1:1: Not in scope: `+-'

What's happening here is that the Haskell parser is reading +- as a single token, and trying to use it as an operator. Once again, a few parentheses get us and ghci looking at the expression in the same way.

ghci> 2+(-3)
-1
ghci> 2+(-3)
-1

Compared to other languages, this unusual treatment of negative numbers is an annoyance, for sure, but it at least represents a reasoned tradeoff. As we mentioned, Haskell lets us define new operators at any time, and choose the precedence and associativity of those operators. The language designers chose to accept a slightly cumbersome syntax for negative numbers in exchange for this expressive power.

Undefined values, and introducing variables

ghci defines at least one well-known mathematical constant for us.

ghci> pi
3.141592653589793
ghci> pi
3.141592653589793

But its coverage of mathematical constants is not great, as we can quickly see. Let's see if Euler's number, e, is available.

ghci> e

<interactive>:1:0: Not in scope: `e'
ghci> e

<interactive>:1:0: Not in scope: `e'

Oh well.

[Note]Note

If the above “not in scope” error message seems a little daunting, don't worry. All it means is that there is no variable defined with the name e.

We can define e ourselves; the let construct allows us to introduce a new variable.

ghci> let e = 2.7182818284590451
ghci> let e = 2.7182818284590451

We can then use our definition of e in arithmetic expressions.

ghci> (e ** pi) - pi
19.99909997918947
ghci> (e ** pi) - pi
19.99909997918947

Comparison and boolean operators

Haskell gives us the usual operators for working with boolean values.

ghci> True
True
ghci> False
False
ghci> True && False
False
ghci> False || True
True
ghci> True
True
ghci> False
False
ghci> True && False
False
ghci> False || True
True

Unlike some other languages, Haskell does not treat the number zero as synonymous with False, nor does it accept non-zero as True.

ghci> True && 1

<interactive>:1:8:
    No instance for (Num Bool)
      arising from the literal `1' at <interactive>:1:8
    Possible fix: add an instance declaration for (Num Bool)
    In the second argument of `(&&)', namely `1'
    In the expression: True && 1
    In the definition of `it': it = True && 1
ghci> True && 1

<interactive>:1:8:
    No instance for (Num Bool)
      arising from the literal `1' at <interactive>:1:8
    Possible fix: add an instance declaration for (Num Bool)
    In the second argument of `(&&)', namely `1'
    In the expression: True && 1
    In the definition of `it': it = True && 1

Comparison operators are mostly familiar from other languages.

ghci> 1 == 1
True
ghci> 2 < 3
True
ghci> 4 >= 3.99
True
ghci> 1 == 1
True
ghci> 2 < 3
True
ghci> 4 >= 3.99
True

There's one exception: the “is not equal” operator is (/=).

ghci> 2 /= 3
True
ghci> 2 /= 3
True

Rational numbers, the Haskell prelude, and modules

In addition to integers and floating point numbers, Haskell supports rational numbers. Haskell coders collect self-contained hunks of code into modules. The integer and floating point numbers, and the operators we've seen so far, are packaged in a module named Prelude.

(The Prelude module is often referred to as “the standard prelude”, because its contents are defined by the Haskell 98 standard. Sometimes, it's simply shortened to “the prelude”.)

The prelude is always implicitly available; we don't need to take any actions to use the types, values, or functions it defines. But to use definitions from other modules, we must import them. To use rational numbers, the module we need to import is named Data.Ratio. We can use a ghci directive named :module to import it.

ghci> :module Data.Ratio
ghci> :module Data.Ratio

The notation for writing a rational number is as follows.

ghci> 7 % 2
7%2
ghci> 7 % 2
7%2

The (%) operator above takes two integers and constructs a rational number from them.

Arithmetic on rational numbers works in the same way as on other types of number, even allowing the same operators.

ghci> 7 % 2 + 2 % 3
25%6
ghci> 7 % 2 + 2 % 3
25%6

Haskell represents a rational number with the lowest denominator it can. For example, the result of the following expression is simplified from 254%7 to something easier to read.

ghci> (22 % 7) * 7
22%1
ghci> (22 % 7) * 7
22%1

Aside: the faces of exponentiation

Is it too early to introduce this? Does it disrupt the flow?

We've already seen an exponentiation operator in Haskell: (^) raises a number to an integer power. The word integer is significant here: if we try to raise a number to the power of a floating point number using the (^) operator, exciting things will happen.

ghci> 12 ^ 2
144
ghci> 12.1 ^ 2
146.41
ghci> 12 ^ 2.1

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from use of `^' at <interactive>:1:0-7
      `Fractional t'
	arising from the literal `2.1' at <interactive>:1:5-7
    Probable fix: add a type signature that fixes these type variable(s)
ghci> 12 ^ 2
144
ghci> 12.1 ^ 2
146.41
ghci> 12 ^ 2.1

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from use of `^' at <interactive>:1:0-7
      `Fractional t'
	arising from the literal `2.1' at <interactive>:1:5-7
    Probable fix: add a type signature that fixes these type variable(s)

Notice from the second example that it doesn't matter whether or not the base is an integer, only that the exponent must be.

There's a further constraint on the exponent that is not immediately obvious: it must be not just an integer, but a non-negative integer.

ghci> 12 ^ 2
144
ghci> 12 ^ (-2)
*** Exception: Prelude.^: negative exponent
ghci> 12 ^ 2
144
ghci> 12 ^ (-2)
*** Exception: Prelude.^: negative exponent

If you think about the simplest definition of exponentiation, which is a number repeatedly multiplied by itself a given number of times, this restriction makes sense.

Haskell's exponentiation operator follows the convention that a number raised to the zeroth power is one. This is why the restriction on the exponent is that it must be non-negative, and not that it must be positive.

ghci> 12 ^ 0
1
ghci> 12 ^ 0
1

Haskell also provides a generalised integer exponentiation operator, (^^). This accepts both positive and negative exponents, following the rule that a number raised to a negative exponent is the reciprocal of the number raised to the positive exponent. Let's try this with both integer and rational bases.

ghci> 12 ^^ (-2)
6.944444444444444e-3
ghci> (12%1) ^^ (-2)
1%144
ghci> 12 ^^ (-2)
6.944444444444444e-3
ghci> (12%1) ^^ (-2)
1%144

Finally, Haskell also gives us a floating point exponentiation operator, (**).

ghci> 12.2 ** 2.1
191.1417880875707
ghci> 12.2 ** 2.1
191.1417880875707

Don't sweat those error messages

Remember the point we made earlier about explicit parentheses often being good? Here's an example of that idea in action, except here the parentheses are necessary, not merely a good idea.

ghci> 22 % 7  *  7 % 22

<interactive>:1:0:
    No instance for (Integral (Ratio t))
      arising from use of `%' at <interactive>:1:0-16
    Possible fix: add an instance declaration for (Integral (Ratio t))
    In the expression: ((22 % 7) * 7) % 22
    In the definition of `it': it = ((22 % 7) * 7) % 22
ghci> 22 % 7  *  7 % 22

<interactive>:1:0:
    No instance for (Integral (Ratio t))
      arising from use of `%' at <interactive>:1:0-16
    Possible fix: add an instance declaration for (Integral (Ratio t))
    In the expression: ((22 % 7) * 7) % 22
    In the definition of `it': it = ((22 % 7) * 7) % 22

Look at that error message; it's detailed, and mentions a lot of concepts we haven't covered yet. We're new to Haskell! How are we supposed to interpret all of that? The first thing we must do is take a deep breath and not worry about the details.

If we step back and gloss over the error message, we can see that ghci is displaying for us the expression that it had trouble with. And it has helpfully added parentheses back into the expression, only look! They're in the wrong places

This isn't the fault of ghci. It just happens that the (%) and (*) operators have the same precedences, so ghci parses the expession from left to right. As a result, it tries to construct a rational from another rational and an integer, instead of from a pair of integers. (If (%) had a higher precedence than (*), the expression would be parsed the way we might have hoped.)

All we have to do to correct this problem is add some explicit parentheses to say what we really mean.

ghci> (22 % 7)  *  (7 % 22)
1%1
ghci> (22 % 7)  *  (7 % 22)
1%1
[Note]Note

The important lesson here is one that we'll be repeating over and over throughout the early sections of this book. If you run into problems, don't panic. You do not need to understand every little detail of what's going on. Early on, all you have to do is figure out enough to make progress through a problem. You don't need instantaneous complete understanding, so don't worry if you don't have it.

Text, strings and lists

If you are familiar with a language like Python, you'll find Haskell's notations for strings, lists and tuples familiar.

A text string is surrounded by double quotes.

ghci> "This is a string."
"This is a string."
ghci> "This is a string."
"This is a string."

As in many languages, we can represent hard-to-print characters by “escaping” them. Haskell's escape characters and escaping rules expand on the conventions established by the C language (for details, see Appendix A, Characters, strings, and escaping rules).

ghci> "Here's a newline -->\n<-- See?"
"Here's a newline -->\n<-- See?"
ghci> "Here's a newline -->\n<-- See?"
"Here's a newline -->\n<-- See?"

A list is surrounded by square brackets, with elements separated by commas.

ghci> [1, 2, 3]
[1,2,3]
ghci> [1, 2, 3]
[1,2,3]

A list can be any length.

ghci> []
[]
ghci> ["foo", "bar", "baz", "quux", "fnord", "xyzzy"]
["foo","bar","baz","quux","fnord","xyzzy"]
ghci> []
[]
ghci> ["foo", "bar", "baz", "quux", "fnord", "xyzzy"]
["foo","bar","baz","quux","fnord","xyzzy"]

All elements of a list must have the same type.

ghci> [1, 2, "buckle my shoe"]

<interactive>:1:1:
    No instance for (Num [Char])
      arising from the literal `1' at <interactive>:1:1
    Possible fix: add an instance declaration for (Num [Char])
    In the expression: 1
    In the expression: [1, 2, "buckle my shoe"]
    In the definition of `it': it = [1, 2, "buckle my shoe"]
ghci> [1, 2, "buckle my shoe"]

<interactive>:1:1:
    No instance for (Num [Char])
      arising from the literal `1' at <interactive>:1:1
    Possible fix: add an instance declaration for (Num [Char])
    In the expression: 1
    In the expression: [1, 2, "buckle my shoe"]
    In the definition of `it': it = [1, 2, "buckle my shoe"]

Once again, ghci's error message is verbose, but it's simply telling us that it can't figure out how to turn the string into a number, so the list isn't properly typed.

When it makes sense to do so, we can write a range of elements, and Haskell will fill in the contents of the list for us.

ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]
ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]

We can specify the size of the step to use by giving the first two elements, followed by the value at which to stop generating the range.

ghci> [1.0,1.25..2.0]
[1.0,1.25,1.5,1.75,2.0]
ghci> [1,4..15]
[1,4,7,10,13]
ghci> [1.0,1.25..2.0]
[1.0,1.25,1.5,1.75,2.0]
ghci> [1,4..15]
[1,4,7,10,13]

Haskell makes a distinction between single characters and text strings. A single character is enclosed in single quotes.

ghci> 'a'
'a'
ghci> 'a'
'a'

In fact, a text string is simply a list of individual characters. Here's a painful way to write a short string, which ghci gives back to us in a more familiar form.

ghci> let a = ['l', 'o', 't', 's', ' ', 'o', 'f', ' ', 'w', 'o', 'r', 'k']
ghci> a
"lots of work"
ghci> a == "lots of work"
True
ghci> let a = ['l', 'o', 't', 's', ' ', 'o', 'f', ' ', 'w', 'o', 'r', 'k']
ghci> a
"lots of work"
ghci> a == "lots of work"
True

First steps with types

Despite all our talk of types, our interactions with ghci have so far been free of much type-related thinking. We haven't told ghci what types we've been using, and it's mostly been willing to accept our input.

The first thing we can do to start explicitly exploring the world of types is to get ghci to tell us more about what it's doing. ghci has a command, :set, that lets us change a few of its default behaviours. We can tell it to print more type information as follows.

ghci> :set +t
ghci> 'c'
'c'
it :: Char
ghci> "foo"
"foo"
it :: [Char]
ghci> :set +t
ghci> 'c'
'c'
it :: Char
ghci> "foo"
"foo"
it :: [Char]

What the +t does is tell ghci to print the type of an expression after the expression. That cryptic it in the output can be very useful: it's actually the name of a special variable, in which ghci stores the result of the last expression we evaluated. Let's break down the meaning of the last line of ghci output, then.

  • It's telling us about the variable it.

  • We can read the text :: as meaning “the value on the left has the type on the right”.

  • And the value on the right is the type in question, namely [Char].

[Note]The joy of “it

That it variable is wonderfully handy when we want to use the result of a prior expression in a new expression.

ghci> it ++ "bar"
"foobar"
it :: [Char]
ghci> it ++ "bar"
"foobar"
it :: [Char]

When evaluating an expression, ghci won't change the value of it until after it's finished. An error in the evaluation will leave it untouched, so we can type possibly bogus expressions with a bit of a safety net.

ghci> it
"foobar"
it :: [Char]
ghci> it ++ 3

<interactive>:1:6:
    No instance for (Num [Char])
      arising from the literal `3' at <interactive>:1:6
    Possible fix: add an instance declaration for (Num [Char])
    In the second argument of `(++)', namely `3'
    In the expression: it ++ 3
    In the definition of `it': it = it ++ 3
ghci> it
"foobar"
it :: [Char]
ghci> it ++ "baz"
"foobarbaz"
it :: [Char]
ghci> it
"foobar"
it :: [Char]
ghci> it ++ 3

<interactive>:1:6:
    No instance for (Num [Char])
      arising from the literal `3' at <interactive>:1:6
    Possible fix: add an instance declaration for (Num [Char])
    In the second argument of `(++)', namely `3'
    In the expression: it ++ 3
    In the definition of `it': it = it ++ 3
ghci> it
"foobar"
it :: [Char]
ghci> it ++ "baz"
"foobarbaz"
it :: [Char]

Coupling it with liberal use of the arrow keys to recall and edit the last expression we typed, and we have a fairly decent environment for interactive experiments, where the cost of mistakes is very low. Take advantage of the opportunity to make cheap, plentiful mistakes when you're exploring the language!

Here are a few more of Haskell's names for types, from expressions of the sort we've already seen.

ghci> 7 ^ 80
40536215597144386832065866109016673800875222251012083746192454448001
it :: Integer
ghci> 7 ^ 80
40536215597144386832065866109016673800875222251012083746192454448001
it :: Integer

Integer is Haskell's arbitrary-precision integer type.

[Note]Type names start with an uppercase letter

Both of the type names we've seen so far, Char and Integer, have started with capital letters. This isn't an accident; Haskell requires type names to start with an uppercase letter, and variable names with a lowercase letter.

Rational numbers don't look quite the same as integers.

ghci> 11 % 29
11%29
it :: Ratio Integer
ghci> 11 % 29
11%29
it :: Ratio Integer

Notice two words on the right hand side of the :: above. We can read this as a Ratio of Integer, and infer that a Ratio will probably need to have values of type Integer as both numerator and denominator. Sure enough, if we try to construct a Ratio where the numerator and denominator are of different types, ghci complains.

ghci> 3.14 % 8

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from use of `%' at <interactive>:1:0-7
      `Fractional t'
	arising from the literal `3.14' at <interactive>:1:0-3
    Probable fix: add a type signature that fixes these type variable(s)
ghci> 3.14 % 8

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from use of `%' at <interactive>:1:0-7
      `Fractional t'
	arising from the literal `3.14' at <interactive>:1:0-3
    Probable fix: add a type signature that fixes these type variable(s)

Although it's initially useful to have :set +t giving us type information for every expression we enter, this is a facility we'll quickly outgrow, simply because it will become redundant: after a while, we'll often know what type we expect an expression to have, so why get ghci to remind us? We can turn off the extra type information at any time.

ghci> :set -t
unrecognised flags: -t
ghci> 2
2
it :: Integer
ghci> :set -t
unrecognised flags: -t
ghci> 2
2
it :: Integer

Even with this facility turned off, we can still get that type information easily when we need it, using another ghci command.

ghci> :type 22 % 7
22 % 7 :: (Integral t) => Ratio t
ghci> "foo"
"foo"
it :: [Char]
ghci> :type it
it :: [Char]
ghci> :type 22 % 7
22 % 7 :: (Integral t) => Ratio t
ghci> "foo"
"foo"
it :: [Char]
ghci> :type it
it :: [Char]

The :type command will print type information for any expression we give it (including it, as we see above). It won't actually evaluate the expression; it only checks its type and prints that.

Exercises

1.

Foo?

Conclusion

In this chapter, we've seen how to install GHC for our environment. We then went on to interactively explore some basic Haskell concepts using ghci the interpreter bundled with GHC. We saw how to evaluate simple expressions.

We dipped a toe into the water of typing.

We also had drilled into us the notion that we don't need to understand, or be intimidated by, every single gripe that ghci throws our way. We'll do just fine with a shallow understanding initially, and rely on practice and more reading to round out our knowledge. Onwards!

Want to stay up to date? Subscribe to the comment feed for this chapter, or the entire book.

Copyright 2007 Bryan O'Sullivan, Don Stewart, and John Goerzen. This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 License. Icons by Paul Davey aka Mattahan.