Polymorphism Solutions
Question 1: Identifying Recursion
We have a list of types and a list of instances.For each type, say whether it is polymorphic and if it is not, link it its instance.
Types:
[a] Maybe a Bool String (Bool, b) a Maybe Int Double Char Int (String, Char)
Instances:
1 "True" ("1", '1') 1.0 '1' True Just 1
Answers:
"True" - String
("1",'1') - (Char , String)
1.0 - Double
True - Bool
Just 1 - Maybe Int
Question 2: Applying Polymorphic Functions
We will now take a look at some examples of useful polymorphic functions. For each of the functions, see if you can work out what they do:
polymorphism0 :: [a] -> a
polymorphism (x:xs) = x
Answer: Extracts the head of a list
polymorph1 :: a -> b -> (a,b)
polymorph1 elem1 elem2 = (elem1, elem2)
Answer: Given two elements this function will output a tupple with the two (in the same order).
polymorph2 :: (Eq a) => [a] -> a -> Int
polymorph2 lst elem = case lst of
[] -> 0
_
| head lst == elem -> 1 + polymorph (tail lst) elem
| otherwise -> polymorph (tail lst) elem
Answer: polymorph2
returns the number of times element
is present in lst
.
polymorph3 :: [a] -> [b] -> [(a,b)]
polymorph3 lst1 lst2
| lst1 == [] || lst2 == [] = []
| otherwise = [(head lst1, head lst2)] ++ polymorph3 (tail lst1) (tail lst2)
Answer: creates a list of tupples with elements of the two lists
polymorph4 :: (Num a) => a -> a -> a
polymorph4 x n
| n =< 1 = 0
| otherwise = x + polymorph4 x (n-1)
Answer: returns x * (n - 1)
but effectively rounds up n
if it is not an integer.
We also have the following list of 5 inputs and outputs:
Inputs:
20 "Green"
[True, True, False] True
2 3
"Turtle"
['x','y','z'] [1, 2, 3]
Outputs:
"T"
[('x', 1), ('y',2), ('z', 3)]
5
(20, "Green")
2
Answers:
polymorphism0 "Turtle" = "T"
polymorphism1 20 "Green" = (20, "Green")
polymorphism2 [True, True, False] True = 2
polymorphism3 ['x','y','z'] [1, 2, 3] = [('x', 1), ('y',2), ('z', 3)]
polymorphism4 2 3 = 5
Question 3: Turning Functions Polymorphic
We have seen many haskell functions so far, but until now none have been polymorphic. Let’s fix this situation! Take these list functions you and make them polymorphic:
Answers:
reverse :: [a] -> [a]
reverse ls = case ls of
[] -> []
x:xs -> reverse(xs) ++ x
length :: [a] -> Int
length [] = 0
length x:xs = 1 + (length xs)
elementRepetition :: Int -> a -> [a]
elementRepetition i s
| i == 0 = []
| i > 0 = i : (elementRepetition (i-1) s)
| otherwise = error "Input is negative"
Question 4: Your Own Polymorphic Functions
Now it is time for you to write your own polymorphic functions! Try write a function isPallindrome
that detects if a list if a pallindrome - the same forwards and backwards.
Here are some examples to test against:
isPallindrome "racecar" = True
isPallindrome [1,2,3,3,2,1] = True
isPallindrome "not a tonne" = False
isPallindrome [Just True, Nothing, Nothing] = False
Answer:
isPallindrome :: [a] -> Bool
isPallindrome x = x == reverse x
(Hint: use the function reverse
that flips a list).