CS 550
Spring 2014
Programming Languages
Thursdays 18:30-21:20
University Crossings 153

Instructor:
Geoffrey Mainland
mainland+cs550@cs.drexel.edu
University Crossings 106
Teaching Assistant:
Mark Boady
mwb33@drexel.edu
Warning! This material is for an old version of the course.
$$ \newcommand{\ox}[1]{\llbracket #1 \rrbracket} $$

Interval sets are a way of representing sets of integers. Sets are represented as a collection of intervals. Intervals are represented by a pair of integers. The type of interval sets that we will use in Haskell is:

type IntSet = [(Int,Int)]

For example, to represent the set {2,3,4,10,11,12,13} we use [(2,4),(10,13)]. The interval (2,4) means that we have 2,3,4 in the set; the interval (10,13) means that we have 10,11,12,13 in the set.

The intervals used in interval sets should satisfy the following invariants:

  1. For any interval (x,y) in a set, x should not be greater than y (so the intervals are not empty); for example (2,5) and (4,4) are OK, but not (7,2).

  2. Two intervals in the same set should not be overlapping (or even touching); for example we cannot have the intervals (2,6) and (4,10) in the same set, they should be replaced by (2,10). we cannot have (3,6) and (7,11) in the same set either, they should be replaced by (3,11)

  3. The intervals in a given interval set should lie in ascending order; for example [(1,3),(5,9),(15,16)] is fine, but not [(5,10),(1,3)].

We provide a skeleton that you need to fill in. Please download the skeleton here, extract the contents of the archive, and commit it to your git repository. Note that the archive contains a single directory named hw5 which you can place directly at ~cs550/git/hw5.

Problem 1: Implementation (50 points total)

Implement the following functions on interval sets, keeping the above properties in mind:

emptyS  :: IntSet                        -- creating the empty set
memberS :: Int -> IntSet -> Bool         -- checking if an integer is in the set
insertS :: Int -> IntSet -> IntSet       -- adding an element
mergeS  :: IntSet -> IntSet -> IntSet    -- set union
deleteS :: Int -> IntSet -> IntSet       -- delete an element from the set

The functions should be robust; for example inserting an element that already exists (or deleting an element that does not exist) should simply return the original set.

Please put your implementation in the file IntSet.hs which we have provided. You must not change the definition of the IntSet type or the type signatures of the above functions.

You will likely want to solve problem 1 and problem 2 simultaneously–your tests will help you write a correct implementation.

Each function is worth 10 points.

I suggest you write and test emptyS and memberS first. Then move on to writing deleteS and its test next. Finally, tackle insertS, mergeS, and their tests.

Hint: Write insertS in terms of mergeS. How do you represent an IntSet containing a single value?

Problem 2: Testing (50 points total)

You must complete the implementations of the following QuickCheck properties in TestSuite.hs. Each test is worth 10 points.

prop_empty :: Bool
prop_member :: Int -> IS -> Bool
prop_merge :: IS -> IS -> Bool
prop_insert :: Int -> IS -> Bool
prop_delete :: Int -> IS -> Bool

We have provided an Arbitrary instance that you can use for testing and a function, model, that takes a value of type IntSet and returns a model of the IntSet. This model consists of a sorted list of integers in the IntSet. This model is an inefficient way to implement a set of integers, but it is easy to reason about. Your tests should use model to relate operations on values of type IntSet to operations on lists of integers.

You will likely want to use the functions sort, which sorts a list, and nub, which removes duplicate entries from a list.

For example, consider the prop_insert test. It should test that the model of the IntSet obtained by inserting a value x into an IntSet s is the same as inserting the value x into the list that is the model of s.