2 Tutorial 1: Getting Started
2.1 Step 1: Getting started
First of all, we need to get to grips with the Haskell interpreter, that is GHCi.
Do the following.
- 1.
- Open a terminal window
- 2.
- Start
ghci
on the command line - 3.
- Use GHCi to calculate the following expressions:
12 * 412 − 15
12 * (412 − 15)
1 / (2*pi)
cos pi
2^2
2**0.5Do you get the results you expect?
- 4.
- Use GHCi to calculate the following expressions:
Do you get the results you expect?
- 5.
- ghci has a number of interpreter commands which are not part of the Haskell language. Such
commands start with a :. Have a look at the list of available commands by typing
:help
You will see some of the listed commands in use later. - 6.
- Exit ghci. You can use either Ctrl-D or the
:quit
command to exit.
2.2 Step 2: Using a script
Although ghci makes a neat calculator out of the box, that’s not quite what we want in this module. To solve complex problems we need to write our own programs, that is, define our own functions. To do this, we use separate text files, called scripts or modules, such as the following FirstScript.hs file.
1−− (C) 2016: Hans Georg Schaathun <hasc@ntnu.no>
2
3module FirstScript where −− Module header
4
5double :: Integer −> Integer −− Function declaration (type)
6double x = 2*x −− Function definition
The first line, and other text following a double dash (--), are comment which is ignored by GHC/GHCi. The module header (Line 3) gives the module name which has to match the file name. The function declaration (Line 5) gives the type of a new function. The double function takes an integer as input and gives an integer as output. Mathematically, we would write . The last line defines the double function. The return value is two times the input value x.
Do the following:
- 1.
- Make a new directory to keep your notes and files for this first tutorial. E.g.
mkdir Week01
- 2.
- Change into the new directory. E.g.
cd Week01
- 3.
- Download the file FirstScript.hs file and put it in the current directory (Week01).
- 4.
- Check the contents of the new file by opening it in your editor, e.g.
gedit FirstScript.hs
- 5.
- Start
ghci
from the command line - 6.
- Load the script using the
:load
command::load FirstScript
Note that the extension
.hs
may be omitted. - 7.
- Test the function by typing
double 5
- 8.
- Try the following
double 2.5
What happens? Remember the function declaration. What input does
double
accept?
2.3 Step 3: Making a script
Now, you are going to make your own simple script/module from scratch.
- 1.
- Make sure that you are in the Week01 directory which you used in the previous step.
You can do this with the following command which prints the absolute path to the current
directory:
pwd
- 2.
- Open an editor to edit a Haskell file. E.g.
gedit MyFirstScript.hs
The name of a Haskell file (script) have to end with .hs and should start with an upper-case letter. E.g. MyFirstScript.hs.
- 3.
- Start with a comment at the top of your file to claim authorship, e.g.
−− John Doe <john@doe.nowhere.invalid>
Comments are ignored by the compiler or interpreter, and are purely a help for human readers.
- 4.
- Define a new module by adding a module header under the comment
module MyFirstScript where
Note that the module name must match the filename without the .hs extension.
- 5.
- Define your first function inside the
greet :: String −> String
greet name = "Hello,␣" ++ name - 6.
- Save the file
- 7.
- Start ghci from the command line
- 8.
- Load your script, e.g.
:l MyFirstScript
:l
:load
. - 9.
- Test the function
greet "John"
- 10.
- You can add more functions to your module. Do not close ghci. Use a different window to add a
new function to your module.
square :: Int −> Int
square n = n*n - 11.
- Returning to ghci, reload the module using
:reload
- 12.
- Test the new function:
square 2
square 5
2.4 Step 4: Working with Integers
One of the fundamental data types is integers. In fact Haskell has two integer types, namely Int and Integer. We shall make a little experiment to see the difference.
- 1.
- Open your text editor with a new file, IntTest.hs is a good name.
- 2.
- Define a function to do exponentiation of Integer.
pow1 :: Integer −> Integer −> Integer
pow1 x y = x^y - 3.
- Define another function to do exponentiation of Int.
pow2 :: Int −> Int −> Int
pow2 x y = x^y - 4.
- Open ghci and load the module you just created.
- 5.
- Test the two functions, with small and big arguments.
pow1 2 10
pow2 2 10
pow1 2 65
pow2 2 65
pow1 3 39
pow2 3 39
What happens? Why do pow1 and pow2 give different answers? Discuss answers with your class mates.
2.5 Step 5: Working with Booleans
Boolean is another fundamental data type, with two possible values, True or False.
- 1.
- Open your editor to create a new Haskell module, e.g. BoolTest.hs
- 2.
- Add the customary comment to identify yourself as author and the module header.
- 3.
- Add a couple of functions:
myNot :: Bool −> Bool
myNot False = True
myNot True = False
myAnd :: Bool −> Bool −> Bool
myAnd True True = True
myAnd _ _ = FalseBoth functions are standard logical operators, the negation (not) and the conjunciton (and).
- 4.
- Start ghci, load your module, and test the above functions, e.g.
myNot False
myNot True
myAnd False False
myAnd False True
myAnd True False
myAnd True TrueAre you happy with the results?
- 5.
- Add functions for logical or (myOr) and exclusive or (myXOR) to your module using pattern matching and literals. There is more than one way of doing it, so just think about the mathematical (logical) meaning and do it your way.
- 6.
- Reload your module and test the new functions. Do they work as intended?
2.6 Step 6: Working with Floating Point Numbers
Many of our algorithms work on real numbers. Unfortunately, the computer does not support real numbers. Instead we have to work with floating point numbers. There are two floating point data types in common use. In Haskell, they are called Float and Double, but they are defined by the CPU architecture and not by the language. Let’s explore this
- 1.
- Why cannot computers work with real numbers?
- 2.
- Start ghci
- 3.
- Compare the following expressions
2**500 :: Double
2**500 :: Float
2**(−500) :: Double
2**(−500) :: Float
The floating point types permit a couple of non-numeric values, namely Infinity, and NaN (Not a Number).
- 4.
- Evaluate each of the following Haskell expressions using GHCi. What value do you expect to
get? What value do you actually get?
1/0
0/0
isNaN (log (−1))
(log (−1)) == (log (−1))
(1/0)*0
isInfinite (0/0)
isInfinite (1/0)
NaN values will usually just propagate through floating point operations, so that NaN in gives NaN out. However, some operations have unpredictable results, so you should check for NaN whenever there is a risk that NaN has occured.
- 5.
- What value do you get from the following expressions:
ceiling (log (−1))
ceiling (0/0)
floor (0/0)
2.7 Step 7: Prefix and in-fix notation
We have seen a couple of functions. For instance:
cos 1
pow1 2 10
pow2 2 10
They are evaluated by writing the function name first, and then a string of arguments. This is called
prefix notation, since the function name prefixes the arguments.
We have also seen a couple of operators. For instance
2 + 2
3 * 5
6 / 2
They are evaluated by writing the operator symbol between two operands. This is called in-fix
notation.
- 1.
- Try the following expressions in GHCi and compare:
2 + 2
(+) 2 2 - 2.
- Try the following expressions and compare:
3 * 5
(*) 3 5 - 3.
- Try the following expressions and compare:
6 / 2
(/) 6 2 - 4.
- Make sure that you have loaded the module defining pow1 and pow2. Try the following
expressions and compare:
pow1 6 2
6 ‘pow1‘ 2 - 5.
- Try the following expressions and compare:
pow2 2 3
2 ‘pow1‘ 3 - 6.
- Try the following expressions and compare:
32 ‘mod‘ 10
mod 32 10 - 7.
- Try the following expressions and compare:
32 ‘div‘ 10
div 32 10 - 8.
- Discuss What is the difference between an operator and a function?