Why aren't these two type definitions equivalent?
Also, why isn't "Num a => a -> a" equivalent to "Num -> Num"? In this case the second example is invalid, correct?
I'm assuming it has to do with Num being a Class and Int being a Type, but I'm not clear on what the difference between a Class and Type is in Haskell and how the difference between them is relevant to what type definitions are allowed and what type definitions are not.
Is there a list of Classes and Types in Haskell somewhere?
CodePudding user response:
No, those are not equivalent. Int x
is a kind error. Int
has kind Type
, and then you're trying to apply it to x
which has also kind Type
. This is like writing 'f' 'x'
on the value level – you're trying to apply the function 'f'
to the value 'x'
but both actually have type Char
. Doesn't work.
By contrast, Num x
is fine, because Num
has kind Type -> Constraint
– so this can be applied to something of kind Type
just fine.
ghci> :k Int
Int :: Type
ghci> :k Num
Num :: Type -> Constraint
But the signature
Num x => x -> x
is not the same as the signature
Int -> Int
although many functions could be defined with either of those signatures. For example, the following both compile without problem:
quadruple :: Int -> Int
quadruple = (*4)
quadruple' :: Num x => x -> x
quadruple' = (*4)
The difference is that quadruple
can only be applied to values of the exact type Int
. For example, quadruple 3.14
is a type error, because you're trying to feed a fractional value as the argument, which is incompatible with the expected Int
input. Whereas quadruple' 3.14
works just fine, by instantiating the x
type-variable to (for example) Double
. The result is then also of type Double
. In other words, the function then specializes to
quadruple'' :: Double -> Double
quadruple'' = quadruple'