Practicals

During the very first practical on Tuesday 2 September, you can have a look at the getting started page that has some small getting started exercises.

Assignments

Deadline Assignment Starting framework Hand in
0. Introduction None PrairieLearn
Fri 12 Sept 23:59 1. Lists Assignment1.hs PrairieLearn
Wed 24 Sept 23:59 2. Data structures Assignment2.hs PrairieLearn
Wed 8 Oct 23:59 3. Game, design document Example game
Example design document
Brightspace
Wed 15 Oct 23:59 4. Type classes Assignment4.hs PrairieLearn
Sun 09 Nov 23:59 5. Game, implementation Example game Brightspace
Sun 11 Jan 23:59 Retake Assignment: Monads RetakeAssignment.hs PrairieLearn

Practicals from previous years

Even if you passed the practicals last year, you still need to submit the solutions via PrairieLearn and do a new game practical from scratch.

Coding style

The most important question you should ask yourself to judge your own coding style is “If another proficient Haskell programmer reads my code, would this be the most readable code I could have written?” Where readable can be understood as the time it would take them to understand what your code tries to accomplish and how it accomplishes this.

To give a concrete example: can you figure out what the following function does?

f [a] = h a  -- Base case: call the helper function h on the element in a singleton list
    where h [] = 0  -- Return zero for the empty list
          h (ss:s) = 1 + h s      -- Add one to the recursive call of h.
f (b:a) = if g b > f a then g b else f a      -- If g b is greater than g a then we return g b, otherwise f a
    where g f = foldr (\f g -> g + 1) 0 f   -- Use foldr and a lambda to recurse over f

And what about this one?

-- Find the length of the longest list in a non-empty list of lists.
lengthOfLongestList :: [[a]] -> Int
lengthOfLongestList = maximum . map length

They are equivalent, but it’s much easier to figure out what the second one does due to proper coding style. The first definition would get you zero points for style, the second definition all of them.

Use and reuse

The most important factor that affects readability is proper use and reuse of existing library functions and syntactic sugar. Some important cases:

Indentation

Naming conventions

Comments

Tools

There are two important tools than can give you feedback on your coding style. The first is ghc, the Haskell compiler itself. It will give warnings about e.g. missing cases etc. Generally, it is a good idea to address these. The second is HLint, a tool designed by Neil Mitchell specifically for giving feedback on your coding style. You can install HLint by opening a command prompt and typing:

cabal update && cabal install hlint

After HLint has been installed you can run it on your source code (which we’ll assume you have named Assignment.hs) by typing:

hlint Assignment.hs

HLint will then output a list of suggestions for improving your coding style. Most, although not all, of these suggestions will help to improve your coding style. Of course, computer programs sometimes mistake about subjective issues like coding style, so always use your common sense as well. For example, hlint will always suggest you change map f (map g) xs into map (f . g) xs (this is called map fusion). If f and g are simple expressions this will generally be an improvement, but if they are already quite complex, this may not help to improve readability.

“bad” functions

For the assignments 0, 1, 2, and 4, try to avoid using the following functions/expressions as they are (usually) bad form/style:

Conditionals => use guards over if-then-else

List => use pattern matching
- head
- tail
- lst !! 0
- lst == []
- lst /= []
- length x == 0
- length x /= 0
- length x > 0

Maybe => use pattern matching
- isJust
- isNothing
- fromJust
- fromMaybe
- x == Nothing
- x /= Nothing

Don't use custom/reimplementations
- of head: f (x:xs) = x
- of tail: f (x:xs) = xs
- of isJust: f (Just x) = True
             f Nothing  = False
- of isNothing: f (Just x) = False
                f Nothing  = True
- of fromJust: f (Just x) = x
- of fromMaybe: f x (Just y) = y
                f x Nothing  = x