CSCI 360 - Survey of Programming Languages
Fall 2014
Assignment 8: Data Structures in Haskell
Purely Functional Data Structures
Implmentation of data structures in a purely functional setting requires
some adaptation. In this assignment, we will explore adaptations for
three interrelated data structures.
Queues
A purely functional queue can be represented by a pair of singly-linked
lists. The first list represents the back-end of the queue; the second list
represents the front-end of the queue. New elements are prepended to the
first list. Elements are removed from the start of the second list. If
the second list is empty, the elements of the first list are transitioned
to the second list.
Type declaration:
data Queue a = Queue ([a],[a]) deriving (Show, Eq)
This module will export the following names:
-
newQueue :: Queue a
-
enqueue :: a -> Queue a -> Queue a
-
dequeue :: Queue a -> (a, Queue a)
-
empty :: Queue a -> Bool
Deques
A deque is a queue to which elements can be appended at both ends,
and from which elements can be removed at both ends. The implementation
is similar to a purely functional queue, except that if either list
becomes empty, half of the elements of the other list are moved to it.
Type declaration:
data Deque a = Deque ([a],[a]) deriving (Show, Eq)
This module will export the following names:
-
newDeque :: Deque a
-
pushFront :: a -> Deque a -> Deque a
-
pushBack :: a -> Deque a -> Deque a
-
popFront :: Deque a -> (a, Deque a)
-
popBack :: Deque a -> (a, Deque a)
-
empty :: Deque a -> Bool
Doubly-linked lists with an Iterator
A doubly-linked list allows an element to be inserted or removed from any
part of the list in constant time. This presumes the presence of an
iterator that points to a position in the list.
This type of list can be implemented in a purely functional manner by
using two singly-linked lists. The first list represents the part of
the list preceding the iterator; the second list represents the part of
the list following the iterator. The iterator moves by shifting elements
from one list to another.
Type declaration:
data List2 a = List2 ([a],[a])
This module will export the following names:
-
empty :: List2 a -> Bool
-
atStart :: List2 a -> Bool
-
atEnd :: List2 a -> Bool
-
goLeft :: List2 a -> List2 a
-
goRight :: List2 a -> List2 a
-
delBefore :: List2 a -> List2 a
-
delAfter :: List2 a -> List2 a
-
peekBefore :: List2 a -> a
-
peekAfter :: List2 a -> a
-
addBefore :: a -> List2 a -> List2 a
-
addAfter :: a -> List2 a -> List2 a
Verification
For each of these three data structures, develop a set of QuickCheck
properties sufficient to demonstrate their correctness. You may include
the properties in each source file for the data structure.
Submission
Submit each data structure in a separate Haskell source file.
Include a block comment in each source file arguing as to why your
chosen QuickCheck properties are sufficient for verifying the correctness
of the data structure.