Reputation: 121
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
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