Question 1: Types and Functions

(a) Give the type of f1, explain what the type means, and give the value of test_f1, where the definitions are:

f1 :: (Num a, Eq a) => a -> [a] -> [a]
f1 k xs = [x+k | x <- xs, x /= k]
test_f1 = f1 3 [2, 3, 4, -1, 5, 3]

(b) Give the type of f2 and the value of test_f2:

f2 f g h x = f (g (h x))
test_f2 = f2 (*2) (+3) (^2) 4

f2 :: (c -> d) -> (b -> c) -> (a -> b) -> a -> d

Value of test_f2: 2 * (3 + (4^2)) = 2 * (3 + 16) = 2 * 19 = 38

Question 2: Monads and Algebraic Data Types

(e) Rewrite the following code using do notation:

validateAndProcess :: Int -> Maybe String
validateAndProcess x =
   checkPositive x >>= \y ->
   checkEven y >>= \z ->
   return (show (z * 2))
 
checkPositive :: Int -> Maybe Int
checkPositive x = if x > 0 then Just x else Nothing
 
checkEven :: Int -> Maybe Int
checkEven x = if even x then Just x else Nothing

Question 3: Equational Reasoning and Functional Composition

(b) Assume that the list xs has a finite (but unbounded) number of elements. Prove that sum (map (2*) xs) = 2 * sum xs using the following definition of sum:

sum :: Num a => [a] -> a
sum [] = 0
sum (x:xs) = x + sum xs

Proof by induction over xs.

Base case: xs = [] sum (map (2*) []) = sum [] = 0 = 2*0 = 2 * sum []

Induction case: Assume sum (map (2*) xs) = 2 * sum xs holds for some xs.

Consider x:xs: sum (map (2*) (x:xs)) = sum ((2_x) : map (2_) xs) = (2_x) + sum (map (2_) xs) = (2*x) + 2 * sum xs (by induction hypothesis) = 2 * (x + sum xs) (by distributivity) = 2 * sum (x:xs) (by definition of sum)

Therefore, sum (map (2*) xs) = 2 * sum xs for all finite lists xs.

(d) Simplify the following lambda expression. Show each step in the reduction, and for each step show which conversion rule you are using.

(\a -> (\b -> a (b b))) (\x -> x) (\y -> y+1) 2

Question 4: Domain Specific Languages and Parsers

(b) Consider a type Color defined as follows:

data Color = Red | Green | Blue | Yellow | Purple | Custom Int Int Int

Write a function blend :: Color Color Color that blends two colors according to these rules:

  • Blending primary colors (Red, Green, Blue) creates secondary colors (Yellow, Purple, Cyan)
  • Blending a primary color with itself returns the same color
  • Blending Custom colors averages their RGB components
  • Other combinations result in a suitable Custom color

(c) Using the Parsec library, write a parser for a simple language of arithmetic expressions that supports addition, subtraction, multiplication, division, and parentheses. The parser should return an abstract syntax tree represented by the following data type:

data Expr = Num Int
         | Add Expr Expr
         | Sub Expr Expr
         | Mul Expr Expr
         | Div Expr Expr
         deriving (Show)