James Johnson
James Johnson

Reputation: 121

How would you define these types in Haskell?

I'm in the process of learning Haskell, but am finding it really difficult to understand what seems to be the most basic of things! For one, understanding types. For example, I don't really understand the types of these functions,

threetimes f x = f (f (f x))

or

triple x = x * 3

Wouldn't triple x and threetimes be of type integer because they take values and apply operations on them?

Also when looking at the last function,

last xs = head (reverse xs)

What is the type of last?

Thanks guys. Sorry if the question seems to basic!

Upvotes: 0

Views: 136

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477533

You can construct the type by looking how the types are applied and what functions you use.

threetimes

Take for instance:

threetimes f x = f (f (f x))

Here we first will assume that f has type a (so f :: a), and x has type b (so x :: b).

Now we take a look at the body of the function, the most inner expression is f x, so that means that f is a function, it takes an x as input, so it is a function f :: b -> c. The type of f x is thus f x :: c. But now we look at f (f x), since f x :: c, thus thus means that the input type for f should be c, but we already set it to b, so as a result we know that b and c are the same type so b ~ c, and f :: b -> b, and f (f x) :: b.

We then take a look at the entire expression f (f (f x)). So that means that the type is b, so we conclude that:

threetimes :: (b -> b) -> b -> b

triple

For triple x, we look at:

triple x = x * 3

Operators are actually a convenient way to write functions, we actually wrote:

triple x = (*) x 3

If we take a look at the (*) function, as well as to the 3 literal, we see that:

(*) :: Num a => a -> a -> a
3 :: Num b => b

So that means that we know that x is of type a (i.e. x :: Num a => a), and the since we thus then apply a Num a => a -> a to 3, then this means that a ~ b, so as a result the type is:

triple :: Num a => a -> a

last

We can again take a look at head and reverse:

reverse :: [a] -> [a]
head :: [b] -> b

So if we now analyze:

last xs = head (reverse xs)

this means that we call reverse with xs as argument, as a result we know that xs :: [a], and that reverse xs :: [a], we then call head with (reverse xs) as argument, so now we know that [a] ~ [b], and as a consequence a ~ b. We also can conclude that head (reverse xs) :: a, so this means that:

last :: [a] -> a

Upvotes: 11

Related Questions