Solutions to the Problem Sheet for LI Functional Programming - Week 2
Polymorphism
Find out the types of the following functions. Decide if they are polymorphic.
Function Type Polymorphic fst(a, b) -> ayes (++)[a] -> [a] -> [a]yes notBool -> Boolno head[a] -> ayes tail[a] -> [a]yes ida -> ayes Explain, in your own words, what the function
zipdoes. In the expressionzip ['x', 'y'] [False], what are the type variablesaandbofzip :: [a] -> [b] -> [(a, b)]instantiated by?The function zip traverses the two lists simultaneously while returning the pairs of the elements it encounters in a new list. If the lists are not the same length, the result will have the length of the shorter list. In the example, we have
a = Charandb = Bool.Find a polymorphic function in the GHC standard library whose type contains 3 type variables or more.
Examples are
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]andflip :: (a -> b -> c) -> b -> a -> c.Read Section 3.7 of Programming in Haskell. Compare the types of the examples given there with the types
ghciindicates.The only one which differs is
length :: Foldable t => t a -> Intwhich is generalized from just the type[a]of lists to arbitrary members of theFoldabletypeclass.
Types and Typeclasses
Run, and understand, the following examples
Expression Result Explanation False == 'c'Error The left side has type Boolwhile the right has typeCharFalse == TrueFalseFalse == notError The left side had type Boolwhile the right has typeBool -> BoolFalse == not TrueTruenot == idError No instance of EqforBool -> Bool[not] == [ (id :: Bool -> Bool) ]Error No instance of EqforBool -> BoolOn type classes
Find all the basic instances of the type class
Boundedthat are defined in the GHC Prelude (the libraries that are loaded when startingghci, without importing any additional libraries). Find out whatminBoundandmaxBoundare for each of the instances.Type minBound maxBound Word018446744073709551615OrderingLTGTInt-92233720368547758089223372036854775807Char\NUL'\1114111'BoolFalseTrueWhat type classes do the type classes
Fractional,Floating,Integralextend? What functions to they provide?Typeclass Extends Provides FractionalNum(/) :: a -> a -> arecip :: a -> afromRational :: Rational -> aFloatingFractionalpi :: aexp :: a -> alog :: a -> a... IntegralReal a,Enum aquot :: a -> a -> arem :: a -> a -> adiv :: a -> a -> a... Another type class:
Which type class defines the function
enumFromTo?EnumEvaluate
enumFromToon elements of each instance of that type class.Type Expression Result WordenumFromTo (1 :: Word) 3[1,2,3]OrderingenumFromTo LT GT[LT,EQ,GT]IntegerenumFromTo (-1 :: Integer) 2[-1,0,1,2]IntenumFromTo (3 :: Int) 5[3,4,5]CharenumFromTo 'c' 'g'"cdefg"BoolenumFromTo True False[]()enumFromTo () ()[()]FloatenumFromTo (1.5 :: Float) 2.5[1.5,2.5]DoubleenumFromTo (1.5 :: Double) 2.5[1.5,2.5]Explain the different output between
:type enumFromTo 4 8and:type enumFromTo 4 (8 :: Int).The former gives
enumFromTo 4 8 :: (Enum a, Num a) => [a]and we see that the type is still polymorphic, since the type of both4and8is ambiguous. The latter specifies that8 :: Intso that Haskell instantiates the type varialbeatoInt.
Functions in Haskell
Using the functions
removeLastandremoveElemfrom Handout - Functions, write a function that removes both the first and the last element of a list.removeFirstAndLast :: [a] -> [a]
removeFirstAndLast = reverse . tail . reverse . tailUsing guarded equations, write a function of type
Int -> Int -> Boolthat returnsTrueif the first argument is greater than the second and less than twice the second.betweenNand2n :: Int -> Int -> Bool
betweenNand2n k n | k > n && k < 2 * n = True
| otherwise = FalseWrite a function to pair each element of a list with its index.
withIndex :: [a] -> [(Int,a)]
withIndex l = zip [0 .. length l - 1] l
withIndex' :: [a] -> [(Int,a)]
withIndex' l = [ (i, l !! i) | i <- [0 .. length l-1] ]Write a function which returns the reverse of a list if its length is greater than 7. Now modify the function so that the cutoff length is a parameter.
reverse7 :: [a] -> [a]
reverse7 l = if (length l > 7) then reverse l else l
reverse7guard :: [a] -> [a]
reverse7guard l | length l > 7 = reverse l
| otherwise = l
reverseParam :: Int -> [a] -> [a]
reverseParam n l | length l > n = reverse l
| otherwise = lWrite a function
orB :: Bool -> Bool -> Boolthat returnsTrueif at least one argument isTrue.orB :: Bool -> Bool -> Bool
orB True True = True
orB True False = True
orB False True = True
orB False False = False
orB' :: Bool -> Bool -> Bool
orB' True _ = True
orB' _ True = True
orB' _ _ = FalseWrite a function
swap :: (a, b) -> (b, a)that swaps the elements of a pair.swap :: (a,b) -> (b,a)
swap (x,y) = (y,x)Define three variants of a function
third :: [a] -> athat returns the third element in any list that contains at least this many elements, usingheadandtailthirdHeadTail :: [a] -> a
thirdHeadTail = head . tail . taillist indexing
!!thirdIndex :: [a] -> a
thirdIndex l = l !! 2pattern matching
thirdMatching :: [a] -> a
thirdMatching (_:_:x:_) = x
Define a function
safetail :: [a] -> [a]that behaves like tail except that it maps[]to[](instead of throwing an error). UsingtailandisEmpty :: [a] -> Bool. Definesafetailusinga conditional expression
isEmpty :: [a] -> Bool
isEmpty [] = True
isEmpty _ = False
safeTailCond :: [a] -> [a]
safeTailCond l = if isEmpty l then [] else tail lguarded equations
safeTailGuard :: [a] -> [a]
sageTailGuard l | isEmpty l = []
| otherwise = tail lpattern matching
safeTailMatch :: [a] -> [a]
safeTailMatch [] = []
safeTailMatch (_:xs) = xs