Home
• Education Page
• Schedule
• Literature
Errata
• Example Code
• Practical Exercises
• Haskell Tutor
• Q & A
• Regulations
• Marks
• Oude Tentamens

All about Haskell – links to tutorials, API documentation, tools, libraries, etc.

Miscellaneous

• Getting Help
• Haskell chat
• Advies Van Eerdere Studenten

Practical Exercises

FP

Practical Advice

Programming is not something you learn from a book. Although it is important that you master the theoretical knowledge, it is important that you write code yourself. Therefore, this course requires you to hand in three practical exercises which will be marked. You can work on them alone or together with a partner, but remember to make this explicit when handing in. Together with the marks for the written exam these will form the basis for your final mark.

Be aware that the time you spend in the "werkcolleges" is not nearly sufficient to complete the practicals. The werkcolleges are rather intended to give you an opportunity to get help with the theoretical exercises from the lecture and to ask about problems that you encountered working on the practicals. Also, please bear in mind that even though the theoretical exercises do not contribute to your marks directly, they are essential for passing the written exam. Do not neglect them! Also make sure that you can do these exercises without the assistance of a computer, since at the exam you will not have access to a computer either. Often the solution looks simple, once you have been presented with the solution. Making the exercise sitting behind an empty piece of paper is something different. All in all, you should assume that this course demands no less effort from you as it is worth in ECTS points (7.5), which equates to about 210 hours of work over about 8 weeks. This equates to about 26.5 hours per week!

At the werkcollege two students will share one computer, but do try to make the exercises without assistance. Both partners can profit of working in a team, but make sure that not the same person is operating the the keyboard all the time. If you have a better grasp on a subject than your partner then try to explain! This is in general a very good way to strengthen your own understanding. Of course you are free to bring your own laptop.

Introductory Practicals (not to be handed in)

Before you approach the first practical we ask you to start at the first session to work through an introductory tutorial and and another one on lists. As a preparation for the second practical, use this tutorial on trees to make yourself familiar with data types. These exercises do not have to be handed in. Based on the trees tutorial, here is another one for a better understanding of monads. Here is the solution for the monad tutorial that has been presented during the last werkcollege: Tuple.hs, StateDo.hs, StateBind.hs, StateTypeSyn.hs, StateData.hs. The code has not been tested. Here is also a simplistic parser implementation based on the state monad. A first attempt (ParserDet.hs) and something that should work: ParserMaybe.hs. Please note that I'm not suggesting that a parser should be implemented that way. This code is rather intended to get a basic understanding about parsers and (more importantly) monads.

Practical 4

The last assignment is about stereograms. The deadline is 8 Jan 2012. Note that this is an additional chance for you to improve your grade and/or to meet the requirements of this course. Your three best submissions (out of 3 or 4) will be included in your final mark. Submission by e-mail this time.

Practical 3

The following weights have been used in computing the marks:
Exercise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 bonus/malus style
Weight 1 1 1 1 2 1 1 8 1 1 8 1 2 2 1 1 1 4 2
The bonus/malus is additive, i.e. a 10 can be reached without a bonus.

The third assignment is about implementing a client/server application for playing poker, based on the second practical. Deadline: before November 1. Here are a few links on network programming with Haskell:

Hint: If you have trouble with networking you can get started simply by leaving out networking but assuming that players will take turns behind the terminal (without checking out the other players hand). You can always come to my office (BBL 570) to ask for help.

A simple Client/Server example

module Client where

import Network
import System.IO

port = PortNumber 9595

main = withSocketsDo $ do
  handle <- connectTo "localhost" port
  hSetBuffering handle LineBuffering
  hPutStrLn handle "Hello Server!"
  hClose handle

module Server where

import Network
import System.IO

port = PortNumber 9595

main = withSocketsDo $ do 
          socket                 <- listenOn port
          (handle, host, portno) <- accept socket
          hSetBuffering handle LineBuffering
          bericht <- hGetLine handle
          putStrLn $ "The client says: " ++ bericht
          hClose handle
          sClose socket
          putStrLn "Server is done."

Installing the network package on Windows

Downloading the network package, required by the third practical, via cabal might cause some trouble for Windows users since it requires the GNU C compiler and some POSIX functionality. It is possible, however, to install the Network module using MinGW? and MSYS. Simply follow the following steps:

  • Go to www.mingw.org
  • Click Downloads and then the green button
  • Download, run and follow the steps of the installer. In the screen "Select component", make sure you also mark "MSYS Basic System". If you forgot this, you will need to either run the installer again or install MSYS seperately
  • After installation, go to MinGW? in your start menu and start the MinGW? shell (might also be called something like 'MinGW bash')
  • Input the following commands: cabal update; cabal install network
  • If you did not receive any error messages, the network package should now be installed and can be used in your Haskell code (use "import Network")

If this didn't work, please let us know with a description of what went wrong; you can run the last command as "cabal -v3 install network" for more verbose error messages and send us those.

People using Mac OS X, particulary Lion, might also run into some trouble. This can probably be solved by downloading the latest version of XCode and running the cabal commands in a terminal. If that didn't work, please let us know.

Practical 2

The second assignment is about Poker. You need to implement the console version of the poker, where you are playing against the machine supplied with simple poker AI. There is a small error in the assignment: In poker the rank "one" doesn't exist. The deadline has been extended by one day (Oct 17, 23:59).

Practical 1

The first assignment is about different implementations of the Thue-Morse sequence and using QuickCheck to test some of its properties. If you want to learn more about the Thue-Morse sequence, please refer to the bibliography of the assignment. The exercise is to be handed in before 26-09 with the Submit system. Please, just submit a .hs (or .lhs) file. Do not paste your code into a Word, PDF, or ISO file!

Additional Information about QuickCheck

The quickCheck function can also be applied to a function with multiple parameters. The function will then be tested with random values for each of these parameters. As a small example to illustrates this would be a test to assert the sum of two numbers is always greater than its operands.
prop_plusMagnifies :: Integer -> Integer -> Bool
prop_plusMagnifies m n = m + n > m && m + n > n 
When running
quickCheck prop_plusMagnifies
the property will be tested for different values for m and n and this test will fail with input 0 for both m and n, which reminds us that the property only holds for numbers strictly greater than 0, which we then include as a precondition to the test:
prop_plusMagnifies :: Integer -> Integer -> Bool
prop_plusMagnifies m n = not (m > 0 && n > 0) || m + n > m && m + n > n 
Now the test will succeed for all possible inputs for m and n. A nicer solution would be to use material implication as defined in the assignment.

Additional Hints

  • Exercise 2: Is tms1 inefficient for all use cases? You can use :set +s to verify.

  • Exercise 3: There is more than one way to solve this, but here is a hint to guide you towards a particularly nice solution. If in the computation of tms2 you feel like you need some sort of cache for previously computed elements, why not use tms2 as the cache? The computation result of constant values that are used multiple times is kept in memory until no longer needed. Don't spend too much time on this if you haven't finished the other exercises yet. It's a bonus...

  • Exercise 5: You can also use a list over Int instead of Bool as a representation for binary numbers.

  • Exercise 6: If you notice that tms6 is not productive (non-termination without output), it is probably due to your implementation of entangle, which is not lazy enough. Thus, even with a correct implementation of entangle (verifiable with tms5), tms6 seems to have stronger requirements in terms of laziness. You can make a function lazier by loosening the requirements on the input. Here, you'd have to try to reduce the amount of pattern matching on the input lists.

  • Exercise 7: The labels are only a suggestion on how you can identify a certain portion of the already produced output. If you are not comfortable with these labels and you find another way to denote the state of the evaluation, you can do so as long as it makes sense.

  • Exercises 8 - 13: The exercises deliberately leaves open different aspects, like wether you test the property for a randomly chosen range or just a single index. Furthermore there is often more than just one correct solution, e.g. one might test a proporty for a given range while another just tests a given index, or one with two parameters while another one has three.

  • Exercises 12 and 13: It is easy to write a check that would not terminate if the given list was in fact not a valid Thue-Morse sequence. You can ignore this case. These exercise are not about the benefit of using QuickCheck, but rather about you showing that you can correctly express the given properties in Haskell.

  • General: Be careful with tabs. While in your source code a tab character looks the same as typically 4 or 8 spaces (depending on the editor), a tab is treated the same as a single space character by GHC.

  • Reminder: Even for correct solutions you might not get high scores. For that you need to write nice Haskell code: remove superfluous parentheses; use sensible indentation; use higher-order functions from the Prelude instead of doing primitive recursion; avoid long, incomprehensible compound expressions, in favour of helper functions with meaningful names.