Question 1: Type Inference and Functions

1a)

Question

Consider a function pairToList that takes a tuple of two elements with identical types, and returns a list containing the same two elements. Give the full definition of this function in Haskell, including its type signature.

1b)

Question

Now consider a function listToPair :: [a] -> Maybe (a,a) that takes a list of two elements and returns a pair containing the same two elements.

1c)

Question

In some ways, listToPair and pairToList are dual functions. Write a simple QuickCheck boolean property to specify this duality.

1d)

Question

Study the Haskell expression below. Explain what it means, and what the resulting value will be.

(fmap.fmap) (+1) (Just (1,2))

1e)

Question

Suppose a Haskell program contains the following definitions:

n = 3 + n
xs = [if x==3 then n else x | x <- [0..5]
k = length xs

Give the values of n, xs, and k. For any undefined value, write bot (for bottom). If k is bot, explain why; if it is not, explain how its value is computed.

1f)

ABSTRACT

Consider a list posInts:: [Int] with value [1, 2, 3, …] which is infinitely long.

(i) Write a definition of posInts.

(ii) Explain how lazy evaluation makes it possible to define infinite data structures like posInts.

Question 2:

Abstract

Haskell’s type inference allows type signatures of Haskell functions to be calculated automatically from a function definition. For each of the following definitions, provide an appropriate, general type signature for func.

2a)

Question

func xs = map (+1) xs

2b)

Question

func x = do

let n = x * 2 let xs = replicate n ’*’ putStrLn xs

func :: Int -> IO () with 2 marks for IO () and 1 mark for Int . Deduct 0.5 marks for: func :: Num a => a -> IO () since replicate requires an integer parameter. replicate :: Int -> a -> [a]

2c)

Question

func f xs = map show (filter f xs)

2d)

Question

 

func f g x = let res = g x in case res of Left e Left (f e) Right r Right r

2e)

Question

func xs ys = zipWith f xs ys

where f x y = do x’ h x y’ h y pure (x’, y’)

h [] = Nothing h (x:_) = Just x

2f)

Question

By default, type signatures are optional in Haskell source code. The GHC compiler has an option -fwarn-missing-signatures that warns programmers if a top-level function body has a missing signature. Give one advantage and one disadvantage of this default behaviour.

Question 3:

Abstract

Acme University has the following percentage/grade/point mappings for student assessments:

PercentageLetter GradeGrade Point
100− 85A5
84− 74B4
73− 63C3
62− 52D2
51− 41E1
40− 0F0

3a)

Question

Write a suitable Haskell data type, called LetterGrade, to represent letter grades A–F inclusive.

data LetterGrade = A | B | C | D | E | F — 1 mark for data keyword — 1 mark for sum type with six values

Award no more than 0.5 marks for a String encoding!

3b)

Question

Define a Haskell function, including type signature, that calculates an integer grade point value from a LetterGrade value.

3c)

Question

Define a Haskell function, including type signature, that calculates a LetterGrade value from an integer percentage.

3d)

Question

A grade point average (GPA) is computed as the average (i.e. arithmetic mean) of a list of grade point scores. Grade point scores are integer values. The GPA is a real number, i.e. a floating-point value. Define a function gpa, including an appropriate type signature, that takes a list of grade point scores and, where possible, returns a GPA value. Pay attention to potential error cases.

gpa :: [Int] Maybe Float — 1 gpa [] = Nothing — 1 gpa xs = if length (filter (\x x<0 || x>5) xs) > 0 — 1 then Nothing — 1 else Just ((fromIntegral length xs)) — 2

3e)

Question

Typeclasses provide a means to write parametric code and ensure that polymorphic functions can utilise common functionality. Outline, perhaps using Haskell code fragments, how you might construct a typeclass that allows you to represent marks as any of letter grades, percentages, and grade points. Explain how typeclass definitions can reduce boilerplate code.