This page includes questions by the instructor (John Boyland) that may appear on the final.
The material on the exam will come from Chapters 15-24 of the textbook. You should be ready to do any of the exercises from the book that do not require research. At least one of the exam questions will be an exercise from the book.
You should be able to define and explain the following concepts:
The interface Dictionary has the following methods:
int size(); boolean isEmpty(); Enumeration keys(); Object get(Object key); Object put(Object key,Object value); // returns previous value (or null)and the Enumeration interface has:
boolean hasMoreElements();
Object nextElement();
Implement a class LinkedDictionary which implements this
interface correctly using a linked list of key-value pairs.
This may seem inefficient, but it is a well-known solution called an
``association list'' and is practical when the lists stay short.
Suppose we represent a maze by a collection of facts such as:
door(a,b). door(b,c). door(c,d). door(d,e). door(d,a).Assume you can go either direction through a door.
Write ``merge sort'' in Haskell. (Don't count the length of the list to divide it in two---just assign alternate elements to the two sublists that will be recursively sorted.) What constraint will its type have?
Suppose I write the following function to find the minimum element of a list:
minlist l = head (mergesort l)If we wrote the function in this way in ML (using ML syntax), it would be (asymptotically) inefficient. Why? Is it inefficient in Haskell? Why or why not?
(Questions on what the result of a program is using various parameter passing modes.)
In Homework #8, you wrote an abstract class AbstractIntSet that had among its methods, one named ``find'' and an abstract method ``iterator''
The basic engine in Prolog consists of solve, resolution and unify. Give the algorithm for the first two.
Answer:
solve (goals) =
if goals is empty then succeed()
else
for each rule R
solve(resolution(rename(R),goals))
repeat on failure
resolution (head:conditions,first:rest)
(unify (head,first))(conditions ++ rest)
optional:
succeed() =
if user presses return then Done
else if user presses ';' fail()
Suppose we have the following rules:
parent(sandy,chris). parent(pat,aidan). parent(pat,sandy). grandparent(X,Z) :- parent(X,Y), parent(Y,Z)Show what happens when we run:
solve([grandparent(A,B)])
Answer the following questions:
(Questions such as the ``Lazy Evaluation'' section of Homework #13
ML is a functional function like Haskell and has functions such as
print : string -> unit (;) : unit -> 'a -> 'aso one can write:
fun inc n = (print "In inc"; n+1)(Notice the use of ``;'' as an infix operator.) Suppose that Haskell provided such functions as predefined:
printString :: String -> () (;) :: () -> a -> a (;) () y = yand then one could write:
inc n = (printString "In inc"; n+1)which is the same as:
inc n = (;)(printString "In inc")(n+1)Why wouldn't this work in Haskell? (Hint: it's something to do with laziness.) Explain!
In a lazy language such as Haskell, one can give the type of an interactive program as
program :: [Char] -> [Char]where the program takes the entire list of input and returns the entire output. Although one can write a function such as this in ML, it couldn't be interactive in ML; it wouldn't be able to prompt for input and generate output that depends on the input. Why not? (Hint: it's something to do with call-by-value.) Explain!
The Haskell I/O system is defined using ``monads'' or actions of type IO T where T is any type. In addition there are two functions that operate on these monads:
Answer the following questions:return :: a -> IO a (<<=) :: IO a -> (a -> IO b) -> IO b
(<<=) :: IO a -> IO b -> IO b
(<<=) :: IO a -> (a -> b) -> IO b
f n = let
a1 = printStr "hello"
in
...
(Recall that printStr has type String -> IO ().)