I tested the numeric coercion by using GHCI:
>> let c = 1 :: Integer
>> 1 / 2
0.5
>> c / 2
<interactive>:15:1: error:
• No instance for (Fractional Integer) arising from a use of ‘/’
• In the expression: c / 2
In an equation for ‘it’: it = c / 2
>> :t (/)
(/) :: Fractional a => a -> a -> a -- (/) needs Fractional type
>> (fromInteger c) / 2
0.5
>>:t fromInteger
fromInteger :: Num a => Integer -> a -- Just convert the Integer to Num not to Fractional
I can use fromInteger
function to convert a Integer type to Num (fromInteger has the type fromInteger :: Num a => Integer -> a
), but I cannot understand that how can the type Num
be converted to Fractional
implicitly?
I know that if an instance has type Fractional
it must have type Num
(class Num a => Fractional a where
), but does it necessary that if an instance has type Num
it can be used as an instance with Fractional
type?
@mnoronha Thanks for your detailed reply. There is only one question confuse me. I know the reason that type a
cannot be used in function (/)
is that type a
is with type Integer
which is not an instance of type class Fractional
(the function (/)
requires that the type of arguments must be instance of Fractional
). What I don't understand is that even by calling fromInteger
to convert the type integer to a
type which be an instance of Num
, it does not mean a
type be an instance of Fractional
(because Fractional type class is more constrained than Num type class, so a
type may not implement some functions required by Fractional type class
). If a
type does not fully fit the condition Fractional type class
requires, how can it be use in the function (/)
which asks the arguments type be instance of Fractional. Sorry for not native speaker and really thanks for your patience!
I tested that if a type only fits the parent type class, it cannot be used in a function which requires more constrained type class.
{-# LANGUAGE OverloadedStrings #-}
module Main where
class ParentAPI a where
printPar :: int -> a -> String
class (ParentAPI a) => SubAPI a where
printSub :: a -> String
data ParentDT = ParentDT Int
instance ParentAPI ParentDT where
printPar i p = "par"
testF :: (SubAPI a) => a -> String
testF a = printSub a
main = do
let m = testF $ ParentDT 10000
return ()
====
test-typeclass.hs:19:11: error:
• No instance for (SubAPI ParentDT) arising from a use of ‘testF’
• In the expression: testF $ ParentDT 10000
In an equation for ‘m’: m = testF $ ParentDT 10000
In the expression:
do { let m = testF $ ParentDT 10000;
return () }
I have found a doc explaining the numeric overloading ambiguity very clearly and may help others with the same confusion.