Spring 2024 -- CS291 Haskell Exam 1) Lazy Evaluation ------------------ Lazy evaluation has a number of advantages, but the top three discussed in class were the following: a) It allowed us to run programs involving infinite lists and other infinite data structures, where eager evaluation would have run forever. For example, we fed [2..] into the sieve-finding function that returned the first N primes. b) It can result in much more efficient execution than one might expect from a "naive" function. We saw multiple examples of this, including: sameOutputs fn1 fn2 low high = (map fn1 [low..high]) == (map fn2 [low..high]) That looks like it will map fn1 and fn2 across entire lists of inputs and then start comparing results, but since the map calls are evaluated incrementally, it stops as soon as a difference is discovered. We saw something similar with sameContents checking to see if two trees contained the same values. c) There are expressions that can be evaluated to completion via lazy evaluation that would crash with an exception if eager evaluation were used. We saw numerous examples of these, for example: head (map (`div` 0) [1..10]) We also discussed some less central advantages like cyclic programming, but for full credit I was looking for two of the three above. 2) changeLabels --------------- -- Here's a recursive version: changeLabels _ _ [] = [] changeLabels old new (p:ps) = (fixer p) : changeLabels old new ps where fixer (Point label cs) = Point (if label==old then new else label) cs -- Here's a non-recursive version: changeLabels old new points = map fixer points where fixer (Point label cs) = Point (if label==old then new else label) cs 3) adjustCoords --------------- -- Here's one way to write it: adjustCoords' fn points = map pointFixer points where pointFixer (Point label coords) = Point label (map fn coords) -- Its type is shown below. The input function is Double->Double -- because our LabeledPoint type says that coords are always Doubles. adjustCoords :: (Double -> Double) -> [LabeledPoint a] -> [LabeledPoint a] 4) mystery Problem ------------------ a) helper returns all of the points whose labels match the input, x. b) list1 is a list of unique labels found in the points. A better name would be something like "allLabels" or "uniqueLabels". c) list2 is a list of integers containing the size of each cluster. A better name would be "sizes" or "clusterSizes". d) The mystery function takes a list of LabeledPoints as its input, and returns the size of the largest cluster found within the list.