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'
