Type inference
In these exercises you should assume the following types:
(+) :: Int -> Int -> Int
even :: Int -> Bool
head :: [a] -> a
(++) :: [a] -> [a] -> [a]
foldr :: (a -> b -> b) -> b -> [a] -> b
map :: (a -> b) -> [a] -> [b]
concat :: [[a]] -> [a]
(.) :: (b -> c) -> (a -> b) -> a -> c
1 atHome
What is the type of head ([3, 2] ++ [2])
? Give the type derivation.
{-
We know that
2, 3 :: Int
so
[3, 2], [2] :: [Int].
Now,
(++) :: [a] -> [a] -> [a]
and
[3, 2], [2] :: [Int]
so it follows that
[3, 2] ++ [2] :: [a] with the constraint that a ~ Int.
That is,
[3 ,2] ++ [2] :: [Int].
Finally,
head :: [a] -> a
and
[3, 2] ++ [2] :: [Int]
implies that
head ([3, 2] ++ [2]) :: a with the constraint that a ~ Int.
That is,
head ([3, 2] ++ [2]) :: Int
-}
2 atHome
What is the type of (+) 3
? Give the type derivation.
{-
We know that
3 :: Int
and
(+) :: Int -> Int -> Int
Therefore,
(+) 3 :: Int -> Int
-}
3 atHome
What is the type of map even
? Give the type derivation.
{-
We know that
map :: (a -> b) -> [a] -> [b]
and
even :: Int -> Bool
Therefore,
map even :: [a] -> [b] with the constraint that (a -> b) ~ (Int -> Bool)
That is,
map even :: [a] -> [b] with the constraints that a ~ Int and b ~ Bool
That is,
map even :: [Int] -> [Bool]
-}
4 atHome
What is the type of map concat
? Give the type derivation.
{-
We know that
map :: (a -> b) -> [a] -> [b]
and
concat :: [[c]] -> [c] (note the fresh type variable we use here to avoid confusion!)
Therefore,
map concat :: [a] -> [b] with the constraint that (a -> b) ~ ([[c]] -> [c])
That is,
map concat :: [a] -> [b] with the constraints that a ~ [[c]] and b ~ [c]
That is,
map concat :: [[[c]]] -> [[c]]
-}
5 inClass
What is the type of map head
? Give the type derivation.
6 atHome
What is the type of reverse . reverse
? Give the type derivation.
{-
First, we note that
reverse . reverse
is syntactic sugar for
(.) reverse reverse
Seeing that function application associates to the left, this is equivalent to
((.) reverse) reverse
Let us syntactically distinguish the two copies of reverse as they might be instantiations of reverse at two different types and write
((.) reverse1) reverse2
We know that
(.) :: (b -> c) -> (a -> b) -> (a -> c)
reverse1 :: [d] -> [d] (note the freshly chosen type variable d, to avoid confusion with existing type variables)
reverse2 :: [e] -> [e] (again a fresh type variable e)
It therefore follows that
reverse . reverse = ((.) reverse1) reverse2 :: a -> c with the constraints (b -> c) ~ ([d] -> [d]) and (a -> b) ~ ([e] -> [e])
Simplifying the constraints gives us that:
b ~ [d]
c ~ [d]
a ~ [e]
b ~ [e]
and therefore that
[d] ~ [e]
We conclude:
reverse . reverse :: a -> c with constraints ... = [e] -> [e]
-}
7 atHome
What is the type of foldr (+)
? Give the type derivation.
8 inClass
What is the type of foldr map
? Give the type derivation.
[a] -> [a -> a] -> [a]
[a] -> [[a -> a]] -> [a]
[a] -> [[a -> a] -> [a]]
[[a]] -> [a -> a] -> [a]
{-
We know that
foldr :: (a -> b -> b) -> b -> [a] -> b
and
map :: (c -> d) -> [c] -> [d] (note the fresh type variables we use here to avoid confusion!)
Therefore,
foldr map :: b -> [a] -> b with the constraint that (a -> b -> b) ~ ((c -> d) -> [c] -> [d])
That is,
foldr map :: b -> [a] -> b with the constraints that a ~ (c -> d), b ~ [c] and b ~ [d]
That is,
foldr map :: b -> [a] -> b with the constraints that a ~ (c -> c) and b ~ [c] (because [c] ~ [d] implies that c ~ d)
That is,
foldr map :: [c] -> [c -> c] -> [c]
Up to renaming of bound type variables (which is irrelevant), this is answer 1.
-}
9 atHome
What is the type of map . foldr
? Give the type derivation.
(a -> a -> a) -> [a] -> [[a] -> a]
(a -> a -> a) -> [b] -> [b -> a]
(b -> a -> a) -> [a] -> [[b] -> a]
(b -> a -> a) -> [b] -> [[a] -> a]
10 atHome
Which of the following is the type of concat . concat
? Give the type derivation.
[[a]] -> [[a]] -> [[a]]
[[a]] -> [[a]] -> [a]
[[[a]]] -> [a]
[a] -> [[a]] -> [a]
11 atHome
What is the type of map map
? Give the type derivation.
{-
We know that
map :: (a -> b) -> [a] -> [b] (we'll use the type variables a and b for the left copy of map)
and also
map :: (c -> d) -> [c] -> [d] (we'll use fresh type variables c and d for the right copy of map, to avoid confusion)
Therefore,
map map :: [a] -> [b] with the constraint that (a -> b) ~ ((c -> d) -> [c] -> [d])
That is,
map map :: [a] -> [b] with the constraints that a ~ (c -> d) and b ~ [c] -> [d] (note that -> associates to the right)
That is,
map map :: [c -> d] -> [[c] -> [d]]
-}
12 inClass
What is the type of map (map map)
? Give the type derivation.
[[a -> b]] -> [[[a] -> [b]]]
[a -> b] -> [[[a] -> [b]]]
[[a -> b]] -> [[[a -> b]]]
[[a -> b] -> [[a] -> [b]]]
Give the type derivation.
{-
We know that
map :: (a -> b) -> [a] -> [b]
and also (from the previous question)
map map :: [c -> d] -> [[c] -> [d]] (note that we use fresh type variables to avoid confusion)
Therefore,
map (map map) :: [a] -> [b] with the constraint that (a -> b) ~ ([c -> d] -> [[c] -> [d]])
That is,
map (map map) :: [a] -> [b] with the constraints that a ~ [c -> d] and b ~ [[c] -> [d]]
That is,
map (map map) :: [[c -> d]] -> [[[c] -> [d]]]
Up to (irrelevant) renaming of bound type variables this is answer 1.
-}
13 atHome
Which observation is correct when comparing the types of (map map)
map
and map (map map)?
- The type of the first is less polymorphic than the type of the second.
- The type of the first is more polymorphic than the type of the second.
- The types are the same, since function composition is associative.
- One of the expressions does not have any type at all.
14 atHome
The function maximum
has type Ord a => [a] -> a
. What is the type
of map maximum
? Can you give a derivation?