CSE 130 Sample Solutions: (Small) Group Project 2 -- PROBLEM 1 -- Part a: SPECIFICATION (signature) module Queue (newQ, emptyQ, enQ, deQ, headQ) where newQ :: Queue a emptyQ :: Queue a -> Bool enQ :: a -> Queue a -> Queue a deQ :: Queue a -> Queue a headQ :: Queue a -> a -- SPECIFCATION (constraints; partial solution) ... assume the queue Q corresponds to a sequence -- enQ --> [e_1,e_2, ..., e_n] -- deQ --> headQ Q will lead e_n deQ Q will lead [e_1,e_2, ..., e_{n-1}] enQ x Q will lead [x, e_1,e_2, ..., e_n] ... -- IMPLEMENTATION (concrete data type) data Queue a = EmptyQueue | QueueC a (Queue a) deriving Show -- IMPLEMENTATION ("code") newQ = EmptyQueue emptyQ EmptyQueue = True emptyQ a = False enQ x EmptyQueue = QueueC x EmptyQueue enQ x y = shift y (QueueC x EmptyQueue) shift :: Queue a -> Queue a -> Queue a shift (QueueC a EmptyQueue) b = QueueC a b shift (QueueC a b) c = QueueC a (shift b c) deQ EmptyQueue = error "ERROR: cannot deQ an empty queue!" deQ (QueueC a b) = b headQ EmptyQueue = error "ERROR: cannot get head of an empty queue!" headQ (QueueC a b) = a -- showQueue is a nicer way to display the contents of a queue. showQueue :: (Show a) => Queue a -> String showQueue EmptyQueue = "" showQueue (QueueC a EmptyQueue) = show a showQueue (QueueC a b) = show a ++ ", " ++ showQueue b {- Problem 2 a: this is only a sketch of the solution. The complete solution needs to include the specification! -} -- good old polymorphic stack: data Stack a = MTstack | Add a (Stack a) deriving Show create :: Stack a create = MTstack push :: a -> Stack a -> Stack a push x s = Add x s pop :: Stack a -> (a, Stack a) pop (Add x s) = (x, s) pop MTstack = error "can't pop from empty stack" -- CHECK THIS OUT: -- pushElements takes a stack and a list of elements -- and pushes those elements on the stack, returning -- the new stack!! pushElements :: Stack a -> [a] -> Stack a pushElements s [] = s pushElements s (x:xs) = pushElements (push x s) xs -- popElements takes a stack on pops off its elements -- into a list! popElements :: Stack a -> [a] popElements MTstack = [] popElements (Add x s) = x : (popElements s) -- EXCERCISE: do popElements using pop and guards intead of -- using the data constructor "Add" directly ... -- and finally: this is what it should look like: -- to reverse a list, you push the "xs" list onto -- the empty stack (=create returns the empty stack) -- and then the elements are popped off reverselist xs = popElements (pushElements create xs) -- same as before but note the "." for function composition -- and the missing "xs" reverselist' = popElements . (pushElements create)