Within two days, we have to get to grips with the basics of Haskell. This is the first tutorial, which you should be able to complete before lunch.
First of all, we need to get to grips with the Haskell
interpreter, that is ghci
.
Note Chrome, Chromium, and Opera do not display math-ml correctly. If none of the mathematical expression in Item 3 below show exponentiation, then you need to switch browser. Firefox, Safari, and Iceweasel work well.
Do the following.
ghci
on the command lineghci 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.
:quit
command to exit.A major benefit of functional programming is that we often get a description which closely resembles natural or mathematical language as we would use it in a textbook or report. Functional languages are often used to define domain-specific languages (DSL), which support simple and intuitive definition of problems and solutions within a specific domain. Simon Thompson gives a simple example in the Pictures module, which gives a simple DSL for image operations.
wget https://hackage.haskell.org/package/Craft3e-0.1.0.10/Craft3e-0.1.0.10.tar.gz
tar xzf Craft3e-0.1.0.10.tar.gz
cd Craft3e-0.1.0.10
:load Pictures
horse
image as ASCII graphics
printPicture horse
Does it look like a horse?
print
function too:
print horse
This shows the raw data representing the image.
You see a list of strings, each string enclosed in double quotes,
and the list enclosed in square brackets with commas to separate
the elements.
We will use the Pictures module for several exercises later.
The ASCII arts used above isn't too pleasing to the eye. There is a variation rendering SVG graphics as well, namely the PicturesSVG module. It requires a browser on the side for the display. Test it, and see that it works.
refresh.html
in a web browser, e.g.
firefox refresh.html &
The ampersand (&) makes the program start in the background,
so that it does not block the command prompt.
ghci PicturesSVG
render horse
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. This is usually done in a text file to be loaded into ghci later.
mkdir Tutorial01
cd Tutorial01
Open an editor to edit a Haskell file. E.g.
gedit MyFirst.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.
-- John Doe <[email protected]>
Comments are ignored by the compiler or interpreter, and are purely a help for human readers.
module MyFirstScript where
Note that the module name must match the filename without the .hs
extension.
greet :: String -> String
greet name = "Hello, " ++ name
:l MyFirstScript
greet "John"
square :: Int -> Int
square n = n*n
:reload
square 5
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.
pow1 :: Integer -> Integer -> Integer
pow1 x y = x^y
pow2 :: Int -> Int -> Int
pow2 x y = x^y
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?
Boolean is another fundamental data type, with two possible values, True or False.
myNot :: Bool -> Bool
myNot False = True
myNot True = False
myAnd :: Bool -> Bool -> Bool
myAnd True True = True
myAnd _ _ = False
Both functions are standard logical operators, the negation (not)
and the conjunciton (and).
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
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).
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.
ceiling (log (-1))
ceiling (0/0)
floor (0/0)
Do Exercises 2.1-2.4 in Simon Thompson's book.