Chapter 2. Getting Started

Table of Contents

Your Haskell environment
Getting started with ghci, the interpreter
Basic interaction: using ghci as a calculator
Simple arithmetic
An arithmetic quirk: writing negative numbers
Boolean logic, operators, and value comparisons
Operator precedence and associativity
Undefined values, and introducing variables
Navigating the thicket of fixity rules
Command line editing in ghci
Lists
Operators on lists
Strings and characters
First steps with types
Exercises
Conclusion

As you read this chapter and the few that follow, it's good to keep in mind that early on, we will sometimes introduce ideas in restricted, simplified form. Haskell is a deep language, and presenting every aspect of a given subject all at once is likely to prove overwhelming. As we build a solid foundation in Haskell, we'll expand upon these initial explanations.

Your Haskell environment

Haskell is a language with many implementations, of which two are in wide use. Hugs is an interpreter that is primarily used for teaching. For real applications, the Glasgow Haskell Compiler (GHC) is much more popular. Compared to Hugs, GHC is more suited to “real work”: it compiles to native code, supports parallel execution, and provides useful performance analysis and debugging tools. For these reasons, GHC is the Haskell implementation that we will be using throughout this book.

GHC has three main components.

  • ghc is an optimizing compiler that generates fast native code.

  • ghci is an interactive interpreter and debugger.

  • runghc is a program for running Haskell programs as scripts, without needing to compile them first.

[Note]How we refer to the components of GHC

When we discuss the GHC system as a whole, we will refer to it as GHC. If we are talking about a specific command, we will mention ghc, ghci, or runghc by name.

In this book, we assume that you're using at least version 6.8.2 of GHC, which was released in 2007. Many of our examples will work unmodified with older versions. However, we recommend using whatever is the newest version available for your platform. If you're using Windows or Mac OS X, you can get started easily and quickly using a prebuilt installer. To obtain a copy of GHC for these platforms, visit the GHC download page, and look for the list of binary packages and installers.

Many Linux distributors, and providers of BSD and other Unix variants, make custom binary packages of GHC available. Because these are built specifically for each environment, they are much easier to install and use than the generic binary packages that are available from the GHC download page. You can find a list of distributions that custom-build GHC at the GHC distribution packages page.

For more detailed information about how to install GHC on a variety of popular platforms, we've provided some instructions in Appendix A, Installing GHC.

Getting started with ghci, the interpreter

The interactive interpreter for GHC is a program named ghci. It lets us enter and evaluate Haskell expressions, explore modules, and debug our code. If you're familiar with Python or Ruby, ghci is somewhat similar to python and irb, the interactive Python and Ruby interpreters.

The ghci command is not a complete interpreter for all of Haskell. We typically cannot copy some code out of a Haskell source file and paste it into ghci: it only accepts expressions and some other directives. In this respect, it's more restrictive than, say, the interactive Python interpreter, which can accept all Python code.

On Unix-like systems, we run ghci as a command in a shell window. On Windows, it's available as a menu item accessible from the Start Menu. For example, if you installed using the GHC installer on Windows XP, you should go to “All Programs”, then “GHC”; you'll then see ghci in the list. (See the section called “Windows” for a screenshot.)

When we run ghci, it displays a startup banner, followed by a Prelude> prompt. Here, we're showing version 6.6.1 run on a Linux box. More recent versions print a shorter banner.

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

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

The word Prelude in the prompt indicates that Prelude, a standard library of useful functions, is loaded and ready to use. When we load other modules or source files, they will show up in the prompt, too.

[Tip]Getting help

If you enter :? at the ghci prompt, it will print a long help message.

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

[Note]About the ghci prompt

The prompt displayed by ghci changes frequently depending on what modules we have loaded. It can often grow long enough to leave little visual room on a single line for our input.

For brevity and consistency, we have replaced ghci's default prompts throughout this book with the prompt string ghci>.

If you want to do this youself, use ghci's :set prompt directive, as follows.

Prelude> :set prompt "ghci> "
ghci>

The prelude is always implicitly available; we don't need to take any actions to use the types, values, or functions it defines. To use definitions from other modules, we must load them into ghci, using the :module command.

ghci> :module + Data.Ratio

Basic interaction: using ghci as a calculator

In addition to providing a convenient interface for testing code fragments, ghci can function as a readily accessible desktop calculator. We can easily express any calculator operation in ghci and, as an added bonus, we can add more complex operations as we become more familiar with Haskell. Even using the interpreter in this simple way can help us to become more comfortable with how Haskell works.

Simple arithmetic

We can immediately start entering expressions, to see what ghci will do with them. Basic arithmetic works similarly to languages like C and Python: we write expressions in infix form, where an operator appears between its operands.

ghci> 2 + 2
4
ghci> 31337 * 101
3165037
ghci> 7.0 / 2.0
3.5

The infix style of writing an expression is just a convenience: we can also write an expression in prefix form, where the operator precedes its arguments. To do this, we must enclose the operator in parentheses.

ghci> 2 + 2
4
ghci> (+) 2 2
4

As the expressions above imply, Haskell has a notion of integers and floating point numbers. Integers can be arbitrarily large. Here, (^) provides integer exponentiation.

ghci> 313 ^ 15
27112218957718876716220410905036741257

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 beyond the simplest expressions.

We'll start by writing a negative number.

ghci> -3
-3

The - above is a unary operator. In other words, we didn't write the single number “-3”; we wrote the number “3”, and applied the operator - to it. The - operator is Haskell's only unary operator, and we can't mix it with infix operators.

ghci> 2 + -3

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

If we want to use the unary minus near an infix operator, we must wrap the expression it applies to in parentheses.

ghci> 2 + (-3)
-1
ghci> 3 + (-(13 * 37))
-478

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

ghci> 2+3
5

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

ghci> 2+-3

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

Here, the Haskell implementation is reading +- as a single operator. Haskell lets us define new operators (a subject that we'll return to later), but we haven't defined this one. Once again, a few parentheses get us and ghci looking at the expression in the same way.

ghci> 2+(-3)
-1

Compared to other languages, this unusual treatment of negative numbers might seem annoying, but it represents a reasoned trade-off. Haskell lets us define new operators at any time. This isn't some kind of esoteric language feature; we'll see quite a few user-defined operators in the chapters ahead. The language designers chose to accept a slightly cumbersome syntax for negative numbers in exchange for this expressive power.

Boolean logic, operators, and value comparisons

The values of Boolean logic in Haskell are True and False. The language uses C-influenced operators for working with Boolean values.

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

Here, (&&) is logical “and”, and (||) is logical “or”.

Unlike some other languages, Haskell does not treat the number zero as synonymous with False, nor does it consider any non-zero value to be 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

Once again, we're faced with a substantial-looking error message. In brief, it tells us that the Boolean type, Bool, is not a member of the family of numeric types, Num. The error message is rather long because ghci is pointing out the location of the problem, and hinting at a possible change we could make that might fix the problem.

[Tip]Remain dauntless in the face of error messages

An important guideline here is one that we'll be repeating over and over throughout the early sections of this book. If you run into problems or error messages that you do not yet understand, don't panic. Early on, all you have to do is figure out enough to make progress through a problem. As you acquire experience, parts of error messages that now seem obscure will become easier to follow.

The numerous error messages have a purpose: they actually help us in writing correct code, by making us perform some amount of debugging “up front”, before we ever run a program. If you are coming from a background of working with more permissive languages, this way of working may come as something of a shock. Bear with us.

Most of Haskell's comparison operators are similar to those used in C and languages influenced by C.

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

There's one exception: the “is not equal to” operator is (/=) (somewhat visually similar to the mathematical ≠ operator), not the (!=) you might expect from a language that borrows many other operators from C.

ghci> 2 /= 3
True

Also, where C and Perl use ! for logical negation, Haskell uses the not function.

ghci> not True
False

Operator precedence and associativity

Like other languages that use infix notation to write some expressions, Haskell has a notion of operator precedence. We can use parentheses to explicitly group parts of an expression, and precedence allows us to omit a few parentheses. For example, the multiplication operator has a higher precedence than the addition operator, so Haskell treats the following two expressions as equivalent.

ghci> 1 + (4 * 4)
17
ghci> 1 + 4 * 4
17

Haskell assigns numeric precedence values to operators, with 1 being the lowest precedence and 9 the highest. A higher-precedence operator gets parsed before a lower-precedence operator. We can use ghci to inspect the precedence levels of individual operators, using its :type command.

ghci> :info (+)
class (Eq a, Show a) => Num a where
  (+) :: a -> a -> a
  ...
  	-- Defined in GHC.Num
infixl 6 +
ghci> :info (*)
class (Eq a, Show a) => Num a where
  ...
  (*) :: a -> a -> a
  ...
  	-- Defined in GHC.Num
infixl 7 *

Since (*) has a higher precedence than (+), we can now see why 1 + 4 * 4 is parsed as 1 + (4 * 4), and not (1 + 4) * 4.

Haskell also defines associativity of operators. This determines whether an expression containing multiple uses of an operator is parsed from left to right, or right to left. The (+) and (*) operators are left associative, which is represented as infixl in the ghci output above. A right associative operator would be displayed with infixr.

The combination of precedence and associativity rules are usually referred to as fixity rules.

Undefined values, and introducing variables

Haskell's prelude, the standard library we mentioned earlier, defines at least one well-known mathematical constant for us.

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'

Oh well.

[Note]Don't worry about the error message

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.

Using ghci's let construct, we can make a temporary definition of e ourselves.

ghci> let e = exp 1

This is a call to the base-e exponential function, exp, and our first example of calling a function in Haskell. While languages like Python require parentheses around the arguments to a function, Haskell does not.

With e defined, we can use it in arithmetic expressions.

ghci> (e ** pi) - pi
19.99909997918947
[Warning]This syntax is ghci-specific

The syntax for let that ghci accepts is not the same as we would use in a normal Haskell program. We'll see the normal syntax in the section called “Introducing local variables”.

Navigating the thicket of fixity rules

It's sometimes 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 completely on operator precedence are notorious sources of bugs. A compiler and a human can easily end up with different notions of what even a short, parenthesis-free expression is supposed to do.

Here's a cautionary example of mixing different operators of the same fixities: (*) and (/). The following two expressions give subtly different results.

ghci> 5 * 8 / 3
13.333333333333334
ghci> 5 * (8 / 3)
13.333333333333332

When deciding whether to use parentheses, you can probably rely on yourself and your readers to remember the language's precedence rules for the most common arithmetic and logical operators: (||) is 2; (&&) is 3; (+) and (-) are 6; while (*) and (/) are 7. For associativities and for other operators, it's not often wise to assume that readers will remember the rules, so parentheses are often safest.

Command line editing in ghci

On most systems, ghci has some amount of command line editing ability. In case you are not familiar with command line editing, 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. On Unix (but not Windows, unfortunately), the tab key completes partially entered identifiers.

[Tip]Where to look for more information

We've barely scratched the surface of command line editing here. Since you can work more effectively if you're more familiar with the capabilities of your command line editing system, you might find it useful to do some further reading.

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

Lists

A list is surrounded by square brackets; the elements are separated by commas.

ghci> [1, 2, 3]
[1,2,3]
[Note]Commas are separators, not terminators

Some languages permit the last element in a list to be followed by an optional trailing comma before a closing bracket, but Haskell doesn't allow this. If you leave in a trailing comma, you'll get a parse error.

A list can be of any length. The empty list is written [].

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

All elements of a list must be of the same type.

ghci> [True, False, "testing"]

<interactive>:1:14:
    Couldn't match expected type `Bool' against inferred type `[Char]'
      Expected type: Bool
      Inferred type: [Char]
    In the expression: "testing"
    In the expression: [True, False, "testing"]

Once again, ghci's error message is verbose, but it's simply telling us that there is no way to turn the string into a Boolean value, so the list expression isn't properly typed.

If we write a series of elements using range notation, Haskell will fill in the contents of the list for us.

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

Here, the .. characters denote a range. We can only use range notation for types whose elements we can enumerate. Range notation makes no sense for rational numbers, for example, because there is not a countable number of rationals.

By the way, notice that the above use of range notation gives us a closed interval; the list contains both endpoints.

When we write a range, we can optionally 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]

In the latter case above, the list is quite sensibly missing the end point of the range, because it isn't an element of the series we defined.

We can omit the end point of a range. If the type we're enumerating has an upper bound on its values (or a lower bound if the step is negative), that bound will be the end point of the range. Otherwise, the range will continue indefinitely. For example, if you type [1..] at the ghci prompt, you'll have to interrupt or kill ghci to get it to stop printing an infinite succession of ever-larger numbers.

[Warning]Beware ranges of floating point numbers

Here's a non-intuitive bit of behaviour.

ghci> [1.0..1.8]
[1.0,2.0]

Behind the scenes, the Haskell implementation is converting the floating point numbers into integers, enumerating the range as integers, then turning them back into floating point numbers.

While this is peculiar, there's worse in store. The range [0,0.1..1] steps in increments of 0.1 between zero and one, but the number of elements in the list depends on the amount of rounding error in the implementation's representation of floating point numbers: you will probably get a list of eleven elements, but you might get ten.

Because of these limitations, range notation over floating point numbers is not really safe to use.

Operators on lists

There are two ubiquitous operators for working with lists. We concatenate two lists using the (++) operator.

ghci> "foo" ++ "bar"
"foobar"
ghci> [] ++ [1,2,3] ++ [4]
[1,2,3,4]

More basic is the (:) operator, which adds an element to the front of a list. This is pronounced “cons” (short for “construct”).

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

Strings and characters

If you know a language like Perl or C, you'll find Haskell's notations for strings familiar.

A text string is surrounded by double quotes.

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 follow the widely used conventions established by the C language. For example, '\n' denotes a newline character, and '\t' is a tab character. For complete details, see Appendix B, Characters, strings, and escaping rules.

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

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

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

First steps with types

While we've talked a little about types already, 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.

Haskell requires type names to start with an uppercase letter, and variable names must start with a lowercase letter. Bear this in mind as you read on; it makes it much easier to follow the names.

The first thing we can do to start 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]

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. (This isn't a Haskell language feature; it's specific to ghci alone.) Let's break down the meaning of the last line of ghci output.

  • It's telling us about the special variable it.

  • We can read text of the form x :: y as meaning “the expression x has the type y”.

  • Here, the expression “it” has the type [Char]. (The name String is often used instead of [Char]. It is simply a synonym for [Char].)

[Tip]The joy of “it

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

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

When evaluating an expression, ghci won't change your environment if the evaluation fails. A successful evaluation will only change either the variable you specify, or it if you didn't name a variable to change. This lets you write potentially bogus expressions with something 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]

When we couple it with liberal use of the arrow keys to recall and edit the last expression we typed, and this gives us 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

Haskell's integer type is named Integer, and is unbounded; only your system's memory capacity limits the size of the integers it can represent.

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

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”. We might infer that a Ratio must 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, or of the same non-integral type, ghci complains.

ghci> 3.14 % 8

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from a 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> 1.2 % 3.4

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t' arising from a use of `%' at <interactive>:1:0-8
      `Fractional t'
        arising from the literal `3.4' at <interactive>:1:6-8
    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: after a while, we'll often know what type we expect an expression to have. We can turn off the extra type information at any time, using the :unset command.

ghci> :unset +t
ghci> 2
2

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

ghci> :type 'a'
'a' :: Char
ghci> "foo"
"foo"
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.