
Daniel Fischer wrote:
Not quite. (/) needs a type which is an instance of Fractional. All instances of Fractional are also instances of Num, so Fractional is more specific than Num. If you divide the result of sum using (/), sum is used at the less general type (Fractional a => [a] -> a). Every function can be used at all types which are less general than its most general type.
Aahh.... I see. The "sum" part is making more sense now. So let's see: "sum" is a (Num a => [a] -> a). Every function can be used at all types that are less general than its most general type. Fractional is a kind of Num. Therefore, "sum" can be used as (Fractional a => [a] -> a) to make it compatible with (/). Thanks for the detailed explanation. It's a lot clearer now.
This surprises me. I would have thought that Fractional is a kind of Num and Int is a kind of Fractional,
No, Int is an instance of Integral, which is sort of the opposite of Fractional. Fractional means that you can freely divide (excluding division by 0 of course), things like 3.24 make sense, Integral means that things like mod or gcd make sense. Though it is possible to make a type an instance of both, Fractional and Integral, that doesn't really make sense.
This helps. I think I see the problem: Suppose that Integral was a kind of Fractional, the way I proposed. What happens when someone writes (x / y) `mod` z ? Trying to apply the same reasoning you used above: (/) :: Fractional a => a -> a -> a mod :: Integral a => a -> a -> a Using the logic that you explained above, we would have to force (/) to give an Integral result, which in general is wrong. And that is a reasonable argument why Integral should not be an instance of Fractional. Am I right more or less?
But I don't really get why.
fromIntegral says, whatever Num type you want, I can give it to you.
... and 'length' says, "whatever Int type you want, I can give it to you", but (/) says "I don't want an Int, I want a Fractional" and that's why 'length' alone doesn't get along with (/). I'm beginning to see the reasoning behind Haskell's behaviour, but I think I'll need time to get used to it. Thanks for the help. Daniel.