[Haskell-beginners] Haskell type system

Paul Sargent psarge at gmail.com
Sun Sep 27 10:52:44 EDT 2009


I'll try my hand at these, anybody feel free to point out all my  
deliberate mistakes.

On 27 Sep 2009, at 11:22, informationen wrote:

> Two functions f and g with the following signatures are given:
> f :: a -> a
> g :: b -> c -> b
>
> A) Give the type of the following expressions:
>
> 1) g [False] True  :: 2) g [] True

These two are simply that the result of the function g is the same as  
it's first argument. The first takes a list of Boolean, the second a  
list of an unknown type. Therefore the results are the same types  
[Boolean] and [a] respectively.

> :: 3) g (f True)      ::

The result of f is the same type as it's argument, in this case Boolean.
g's first and only argument which is the type of the result of f --  
Boolean.
As we haven't specified a second argument, the returned type is a  
function which takes an unknown type and returns a boolean.

(c -> Bool)


> 4) g f             ::

Similar to the last case except now the only argument supplied is a  
function of type (a -> a).
(c -> (a -> a))

> Answers:
>
> B) Which of the following statements is correct?
>
First two are easy, and the same.
> 1)  g f 1           c -> Int
> 2)  g (f 1)         c -> Int

Remember that the type of (.) is (b -> c) -> (a -> b) -> a -> c. That  
is, it takes two functions where they both take an argument, and the  
type of the first functions argument is the same as the seconds result.

> 3)  g . (f 1)

Here (f 1) doesn't take an argument, it's already supplied. That makes  
it's type Int, not (a -> b). That's not right.

> 4)  g . f 1

The same, the brackets where redundant in the previous expression.

> 5)  (g . f) 1

Here we're composing before giving the arguments.
So, remembering that f :: a -> a and g :: b -> c -> b, we can start  
filling in the types:

(b -> c) -> (a -> b) -> a -> c               -- To make g fit, c must  
become (c -> b)
(b -> (c -> b)) -> (a -> b) -> a -> (c -> b) -- f returns same type as  
input, so b == a
(a -> (c -> a)) -> (a -> a) -> a -> (c -> a) -- Now we've supplied f  
and g we can just worry about the result part
a -> (c -> a)                                -- This is the type of  
(g . f), but we've got an Int argument "1"
Int -> (c -> Int)                            -- So the type of the  
expression is (c->Int)

Nothing wrong with that. Type safe.

It might be easier to just start plugging types in than following that  
explanation, but it does work.

> C) A function h is given as: h p x = p (f x). Which of the following
> statements is correct.

p is obviously a function of one (or more) arguments. h takes two  
arguments, and returns the result of p, so

h :: (a -> b) -> c -> b

because we know f :: a -> a, we can say a and c are the same type

h :: (a -> b) -> a -> b

That's number 3.

(g . f) x is the same as g (f x). Therefore we can re-write h

h' p x = (p . f) x -- or
h' p = (p . f)     -- the argument is implicit

That's 4

> 3) h :: (a -> b) -> a -> b
> 4) h is equivalent to h' with h' p = p . f



More information about the Beginners mailing list