Friday, July 3, 2009

Solutions to Chapter 12 (p. 274)

#1. Trivially,

getElem4 :: (t,t,t,t) -> Int -> t
getElem4 (a,_,_,_) 0 = a
getElem4 (_,b,_,_) 1 = b
getElem4 (_,_,c,_) 2 = c
getElem4 (_,_,_,d) 3 = d

#2. Not too different:

getElem6 :: (t,t,t,t,t,t) -> Int -> t
getElem6 (a,_,_,_,_,_) 0 = a
getElem6 (_,b,_,_,_,_) 1 = b
getElem6 (_,_,c,_,_,_) 2 = c
getElem6 (_,_,_,d,_,_) 3 = d
getElem6 (_,_,_,_,e,_) 4 = e
getElem6 (_,_,_,_,_,f) 5 = f

#3. There are two ways to go about this. First, we can implement getElem6 in terms of getElem4, like this:

getElem6' :: (t,t,t,t,t,t) -> Int -> t
getElem6' (a,b,c,d,e,f) i
  | i < 4     = getElem4 (a,b,c,d) i
  | otherwise = getElem4 (c,d,e,f) (i - 2)

Note how the error cases are handled -- whenever we hand of an invalid index, it is getElem4 that will encounter and report the problem.

The second approach is to implement getElem4 in terms of getElem6. But how do we build a six-tuple when all we're given is a four-tuple? We could, for example, copy the 1st element twice (at the end), i.e., given (a,b,c,d), pass the constructed value (a,b,c,d,a,a) to getElem6. While this ensures the synthesized elements are of the correct type, we'd get the wrong result for indexes 4 and 5, unless we add our own error-checking.

A better alternative lies in directly indicating these values don't really exist, and any attempt to access them is an error:

getElem4' :: (t,t,t,t) -> Int -> t
getElem4' (a,b,c,d) i = getElem6 (a,b,c,d,er,er) i
    where er = error "Out of range"

No comments:

Post a Comment