3
votes

I am reading Type classes, Chapter 2 of Learn You Haskell For Great Good. My question is why 4 + 3.2 works but not length [1, 2, 3, 4] + 3.2, why do we need to use fromIntegral function in second case. Is there no relation between Num and Integral type classes. How do I find what classes a type is instance of ?

2

2 Answers

4
votes

In cases like this use ghci to check the types, for example it will tell you for your first input:

Prelude> :t 4 + 3.2
4 + 3.2 :: Fractional a => a

here the fromInteger is implicit (the 4) used.

In the second case you have the problem, that length is :: [a] -> Int (a bit different in newer GHCs) and 3.2 is still :: Fractional a => a but (+) is :: Num a => a -> a -> a (it needs the same type of parameters a) - now Int is not an instance of Fractional and you get the error.


How to find the classes a type is instance of

PS (the original answer to that is gone) - the easiest way is using GHCi using :i itself:

Prelude> :i 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.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’

but please remember that this will depend on the loaded modules - for example when you import Test.QuickCheck you will see that Int now instance of Arbitrary too:

Prelude Test.QuickCheck> :i 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.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
instance [overlap ok] [safe] CoArbitrary Int
  -- Defined in ‘Test.QuickCheck.Arbitrary’
instance [overlap ok] [safe] Arbitrary Int
  -- Defined in ‘Test.QuickCheck.Arbitrary’
0
votes

length fixes its output type as Int (which is incompatible with 3.2) rather than any Num. The function you are looking for is:

genericLength :: Num i => [b] -> i