Constrained polymorphism: variable parameter vs. function
This is a very simple question. I've just started learning Haskell using several different sources. I am currently unable to decipher them.
The following will naturally look fine.
g :: Num a => a -> a
g x = x + 2
h = g (1.0 :: Double)
This example of limited polymorphism makes perfect sense to me when I interpret it like this: as long as the parameter provided g
is of type having an instance Num
, everything is fine.
So, consider the following.
x :: Num a => a
If I interpret this as above, I get: x
can take any value of a type that has an instance Num
. However, the following types will not appear.
x :: Num a => a x = (1.0 :: Double)
My question is, what's the difference?
I kind of understand what could happen: the second example x
is defined so that it will evaluate any Num
, and (1.0 :: Double)
not fit.
But my vague idea is far from being fully explained, and I'm looking for a better one.
You should read the type g :: Num a => a -> a
like this:
- the caller
g
selects the typea
- the caller must prove that it
a
is a numeric type - the caller must provide the value of the type argument
a
-
g
must then respond with a result likea
Therefore, x :: Num a => a
it becomes
- user
x
selects typea
- the user must prove that he
a
is a numeric type -
x
must then respond with a result likea
So, it is x
not allowed to choose a = Double
, the user x
gets the choice. Think for example. from (x :: Int) + 4
: this will check the type when choosing a=Int
. The implementation x
must be generic, so work with all numeric types.
By the way, note that numeric literals are of the same type 42 :: Num a => a
, so we can use them like Double
, like Int
any other numeric type.