I'm assuming you have downloaded this respository, either by using git to clone it or simply by downloading a zip file from github, and have the Haskell toolchain installed.
Within a terminal, cd
to the directory this file is in:
<path-to-the-repository>/labs/week1
. Start the haskell interpreter
by typing cabal repl
. This is what that looks like on my system:
$ cabal repl
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- week1-0.1.0.0 (exe:week1) (first run)
Configuring executable 'week1' for week1-0.1.0.0..
Preprocessing executable 'week1' for week1-0.1.0.0..
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Week1 ( src/Week1.hs, interpreted )
Ok, one module loaded.
ghci>
Note that this command has loaded the Haskell script Week1.hs
, which
is currently empty, into ghci
. You can type any Haskell expression
into the ghci
"REPL" (Read-Eval-Print-Loop) and it will be
evaluated. Enter a list of the integers from 1 to 10 using the range
syntax:
λ> [1..10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In the lectures we mentioned the standard functions map
and filter
. There is also a standard
function called odd
, which takes an integer and returns True
if that number is odd. Try using
map
and filter
with the odd
function and the list from the previous step:
λ> map odd [1..10]
[True, False, True, False, True, False, True, False, True, False]
λ> filter odd [1..10]
[1, 3, 5, 7, 9]
Use your favourite text editor to edit the file
labs/week1/src/Week1.hs
, adding this content:
test :: String
test = "Hello World!"
Going back to the terminal, reload your work and test it like so:
> :reload
> test
(Note that you can type :r
as an abbreviation for :reload
. You can also use
tab-completion in ghci
and the up arrow to get back to previous entries.) Add
your solutions to all of the following problems to
Week1.hs
. Whenever you make changes you need to reload the file in
the REPL.
-
Edit
Week1.hs
to write a functionsquare :: Int -> Int
which returns the square of a number. Test your work in ghci as follows:> :reload > square 5
Try calling
square
with a few numbers. What happens when you executesquare True
? -
Use
square
to write a functionsumsquare :: Int -> Int -> Int
which returns the sum of the squares of its two arguments. -
Write a recursive function
elem
which takes two arguments, a value and a list of values of the same type, and returns a boolean.Your function should use pattern matching to return
True
if the first argument is an element of the list (hence the name). There should be two equations in the definition of the function -- the first will be one which pattern matches the empty list. This should returnFalse
, since nothing is an element of the empty list. The second case, which deals with non-empty lists, should returnTrue
if the element to be found is equal to the head of the list. If not, the function should return the result of calling itself recursively on the tail of the list. Your function will have the structure below.Note the typeclass constraint
Eq a
-- the type of the things in the list,a
, must be a type that can be compared for equality:elem :: Eq a => a -> [a] -> Bool elem x [] = ... elem x (y:ys) = ...
-
Write a (recursive) function
length :: [a] -> Int
which calculates the length of a list. Use pattern matching to write an equation for the empty list (what is its length?) and the case when the list contains elements. Recursively, the length of a list with a head and a tail is one plus the length of the tail. -
Write a function
drop :: Int -> [a] -> [a]
, wheredrop n xs
returnsxs
with its firstn
elements removed. Make a function with three equations using pattern matching:drop :: Int -> [a] -> [a] drop 0 xs = ... drop n [] = ... drop n (x:xs) = ...
So you need to think about how to drop zero elements from a list, how to drop
n
(any number) of elements from the empty list, and how to dropn
elements from a list with a head and a tail (recursively, drop the head then dropn-1
elements from the tail. -
Write a function
take :: Int -> [a] -> [a]
, wheretake n xs
returns the firstn
elements ofxs
as a list (ifxs
contains less thann
elements, your function should return all ofxs
). The definition will be similar todrop
except that in the recursive case you have to use "cons",(:)
, to build up the list that you will return. That is, to taken
items from a list with a head and a tail, you will need to cons the head onto a list which is the result of takingn-1
elements from the tail.