COMP1011 Exercises for Week 08
Computing 1A 05s2 Last updated Tue 19 Jul 2005 14:37

Lab Exercises Week 8

User-defined Types & Unix

The second part of this week's lab is about Unix. Please keep in mind that the Unix material covered in the lectures, tutes, and labs is assessable material, just like programming in Haskell. To solve this week's Unix exercises, you will need to understand how a couple of basic Unix tools work, which means that you have to read some additional documentation about these tools. You won't be able to do this in the supervised lab time. Hence, you should read the documentation before going to your lab and tute; see Ex 2 below for details on what to read.

Ex 1:

This week's exercises require the use of three different modules: BookVideoCD.hs, ProductDB.hs, and Lab08.hs. You will create the first two modules in the following, first exercise. All the code implemented in the remaining exercises should go into the third module Lab08.hs.

A Store for Books, Videos, and CDs

Implement a module with the following interface

module BookVideoCD (
  Title, Author, Artist, Product(..), getTitle
) where

containing the types and functions from the tutorial exercises. Furthermore, download the module ProductDB.hs.

List the book authors: bookAuthors

Implement a function

bookAuthors :: [Product] -> [Author]

that returns all book authors in a given product list. Use the function List.nub to remove duplicates from the list of authors. The module List is part of the Haskell standard libraries and you can import it without having to define the module. Apply nub to lists like [1,2,1,1] to see what it does, before using it.

Pretty print a product list

Next, implement a function that allows us to print a product list in a nice format. If we just print a product list, we get

Lab08> print products
[Book "Snowcrash" "Neil Stephenson",CD "Death to the Pixies" "The Pixies" 12,
CD "101 Damnations" "Carter USM" 11,Video "Underworld",Book "Consider Phlebas"
"Iain M. Banks",CD "Empires" "VNV Nation" 10,Video "The Matrix",Book 
"Excession" "Iain M. Banks"]

which obviously doesn't look very nice. We attack the problem of producing some nice output in two steps: First, we implement a function showProduct, which produces a nice output for a single product; and second, we implement showProducts, which does the same for a list of products (of course by using showProduct).

The two functions have the following type signatures:

showProduct  :: Product -> String
showProducts :: [Product] -> String

So, they just convert a product, or list of products, into a string, which we, then, can print using putStr. For example, we have

Lab08> putStr (showProduct (CD "Empires" "VNV Nation" 10))
CD   : "Empires", VNV Nation; 10 tracks
Lab08> putStr (showProducts products)
Book : "Snowcrash", Neil Stephenson
CD   : "Death to the Pixies", The Pixies; 17 tracks
CD   : "101 Damnations", Carter USM; 11 tracks
Video: "Underworld"
Book : "Consider Phlebas", Iain M. Banks
CD   : "Empires", VNV Nation; 10 tracks
Video: "The Matrix"
Book : "Excession", Iain M. Banks

Here are some hints that should help you with the exercise:

When you have completed the above exercises show them to your tutor for this week's core mark.

Ex 2:

In the lecture, we saw a number of Unix tools without discussing, in any detail, their working and the many options they take. To look up the details of these tools, you have got a number of alternatives:

Normalised lines of code (LoC)

Implement a shell script that prints the sum of the number of lines of all Haskell files in the current directory disregarding empty lines and lines that start with -- (i.e., dash dash, and hence, contain no code, but only contain a comment).

Hint: Read up on how to use the Unix tool grep. Keep in mind that you don't have to understand all the details about grep (of which there are many), but you definitely need to understand the basics of how regular expressions work.

Hint #2: Have a look at the options taken by the command wc. There is an easier way to restrict its output to the lines of a file (omitting the word and character count) than that discussed in the lecture and tute.

When you have completed the above exercise show them to your tutor for this week's advanced mark.

Additional Exercises

The following are additional exercises to help you getting practice in programming. They are not part of the lab mark, but should help you understand some of the material covered in the lecture.

Search for a title: lookupTitle

Implement a function

lookupTitle :: Title -> [Product] -> Maybe Product

that extracts a product with matching title from the product list if present. If there is no product with the given title in the database, Nothing is returned. For example,

Lab08> lookupTitle "101 Damnations" products
Just (CD "101 Damnations" "Carter USM" 11)
Lab08> lookupTitle "Consider Phlebas" products
Just (Book "Consider Phlebas" "Iain M. Banks")
Lab08> lookupTitle "Dark Star" products

Important Note: Maybe a is already predefined in the Prelude. So, just use it without explicitly adding the definition to your module.

Extract a product list by titles: lookupTitles

Next, implement

lookupTitles :: [Title] -> [Product] -> [Product]

Given a list of titles, this function extracts, for each title, the corresponding product from the second list. Titles that have no matching product in the list are ignored. You must use lookupTitle to do the actual lookup for each title. Examples of the application of lookupTitles are

Lab08> lookupTitles [] products
Lab08> lookupTitles ["Excession", "Dark Star", "Snowcrash"] products
[Book "Excession" "Iain M. Banks",Book "Snowcrash" "Neil Stephenson"]
Lab08> lookupTitles ["Dark Star", "Boys Don't Cry"] products
Lab08> putStr (showProducts (lookupTitles ["Excession", "Dark Star", "Snowcrash"] products))
Book : "Excession", Iain M. Banks
Book : "Snowcrash", Neil Stephenson

Hint: The higher-order function map can again save you one recursive definition. However, this time the use of map is a bit more complicated. In fact, you must in addition use a local function definition (ie, one in a where clause).

The function showProducts revisited

Re-implement showProducts such that the output is in tabular form, i.e.,

Lab08> putStr (showProducts products)
Book : "Snowcrash"           Neil Stephenson
CD   : "Death to the Pixies" The Pixies      17 tracks
CD   : "101 Damnations"      Carter USM      11 tracks
Video: "Underworld"
Book : "Consider Phlebas"    Iain M. Banks
CD   : "Empires"	     VNV Nation      10 tracks
Video: "The Matrix"
Book : "Excession"           Iain M. Banks

The tricky part here is that you cannot make any assumptions about the length of the longest title or author and artist. In other words, if the product database is extended by a product, which has an even longer title, your function should still print a properly aligned table.

Hint: showProduct in its current form is not a suitable helper function for this improved version of showProducts.