
2009/04/23 Daniel Carrera
It looks like (/) is happy with Num but doesn't like Int. This surprises me. I would have thought that Fractional is a kind of Num and Int is a kind of Fractional, so a function that expects Fractional would be happy with an Int but maybe not with a Num. But clearly that's not the way it works.
In GHCi, let's have a look: Prelude> :info Int data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in GHC.Types instance Bounded Int -- Defined in GHC.Enum instance Enum Int -- Defined in GHC.Enum instance Eq Int -- Defined in GHC.Base instance Integral Int -- Defined in GHC.Real instance Num Int -- Defined in GHC.Num instance Ord Int -- Defined in GHC.Base instance Read Int -- Defined in GHC.Read instance Real Int -- Defined in GHC.Real instance Show Int -- Defined in GHC.Show So `Int` is not actually a kind of `Fractional` (it's `Integral`, in fact). Prelude> :t (/) (/) :: forall a. (Fractional a) => a -> a -> a So `(/)` needs some `t` that is in `Fractional`.
'fromIntegral' converts Int to Num. So obviously, Num is good and Int is bad. But I don't really get why.
Actually, `fromIntegral` takes any type `t` that is in `Integral` and makes it into some other type in `Num` as appropriate. You can use `fromIntegral` to go from `Int` to `Integer` or `Word32`, as well. To work with `(/)` we need a type that is in `Num` and in `Fractional`. The compiler defaults these *class constraints* to select, say `Double`. Then `fromIntegral` -- which can take any `Num` to any other `Num` -- does the "cast" from `Int` to `Double` for us. -- Jason Dusek