Haskell – Assignment 2

This assignment is worth 34 points.

Notes:

Problem 1 – zipWith' (8 pts.)

Recall the functionality provided by map, zip, and zipWith:

map not [True, False, True]
=> [not True, not False, not True]
=> [False, True, False]

Note: The middle line of the map example above is meant to help you understand how map works by breaking it down a bit.

zip [1, 2, 3] ['a', 'b', 'c']
=> [(1, 'a'), (2, 'b'), (3, 'c')]
zipWith (+) [1, 2, 3] [4, 5, 6]
=> [(+) 1 4, (+) 2 5, (+) 3 6]
=> [5, 7, 9]

zipWith (&&) [True, True] [False, True]
=> [(&&) True False, (&&) True True]
=> [False, True]

Note: Remember, + and && are just symbols that represent infix functions. When we use them as (+) and (&&), we’re calling them as prefix functions rather than infix functions.

Also recall their type signatures:

map :: (a -> b) -> [a] -> [b]
zip :: [a] -> [b] -> [(a, b)]
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

Implement zipWith using map and zip. Call your function zipWith' so that the name doesn’t conflict with the existing zipWith function.

Problem 2 – List Comprehensions (6 pts.)

Define the following functions using list comprehensions.

2 pts. each

a. caps should return all of the capital letters of the input list.

caps ['A', 'B', 'c', 'd', 'E']
=> "ABE"

b. sumOdd should calculate the sum of the odd numbers in a list.

sumOdd [1..5]
=> 9

c. negsInList should calculate the number of negative elements in a list.

negsInList [1, 2, 3]
=> 0

negsInList [1, -2, -3]
=> 2

Problem 3 – maybeElem (2 pts.)

The elem function (included in the Haskell standard library, Prelude) returns True if an element is in a list and False otherwise.

elem 1 [1, 2, 3]
=> True

elem 0 [1, 2, 3]
=> False

Write a function called maybeElem that returns Just <value> if the input value is in the list and Nothing otherwise.

maybeElem 1 [1, 2, 3]
=> Just 1

maybeElem 0 [1, 2, 3]
=> Nothing

Problem 4 – Expression Types (9 pts.)

Each of these sub-problems relates to chapter 4 of LYAH.

3 pts. each

a. as patterns

Write a function named courseMajor that accepts a CSM course number and returns a sentence about the major with the form "<course_num> is a <major> course". Assume that <major> is the first two characters of the <course_num>. You must use an as pattern in your function definition.

courseMajor "CSCI400"
=> "CSCI400 is a CS course"

courseMajor "PHGN100"
=> "PHGN100 is a PH course"

b. where-clause

Write a function named calcAreas that takes a list of tuples of the form (<length>, <width>) and returns a list of areas. In your calcAreas function, you must use a where clause to define a helper function.

calcAreas [(3, 4), (6, 7), (1, 0)]
=> [12, 42, 0]

c. guards

Write a function named orderTwo that takes a tuple of two orderable values of the same type and returns a tuple with the values in ascending order. You must use a guard expression to define your function.

Hint: Read the above description carefully, the type signature is important here and should be as general as possible.

orderTwo (2, 3)
=> (2, 3)

orderTwo (3.5, 2)
=> (2.0, 3.5)

orderTwo ('b', 'a')
=> ('a', 'b')

Problem 5 – Higher-Order Functions (9 pts.)

3 pts. each

a. swap, swapAll

Write a function named swap that accepts a tuple and swaps the two elements. Then, write a function called swapAll that works on a list of tuples. You must use map in your definition of swapAll.

swap (4, 5)
=> (5, 4)

swapAll [(4, 5), (6, 4), (25, 36)]
=> [(5, 4), (4, 6), (36, 25)]

b. applyIfTrue

Write a function called applyIfTrue that takes 3 parameters: a function, a value, and a boolean. If the boolean is True, then you should return the result of applying the function to the value. Otherwise, just return the original value.

applyIfTrue (*3) 5 True
=> 15

applyIfTrue (*3) 5 False
=> 5

applyIfTrue ((++) "no ") "thanks" True
=> "No thanks"

applyIfTrue ((++) "no ") "thanks" False
=> "thanks"

c. calcArea

Write a function called calcArea that accepts two lists, one of lengths and one of widths, and returns a single list of areas.

calcArea [1, 2, 3] [4, 5, 6]
=> [4, 10, 18]

calcArea [0, 1.1, 2.2] [1, 3, 4]
=> [0, 3.3, 8.8]