Num a ~ Integer / default instance in GHC

Making a library such as cadsim, one encounters the need to provide functions that accept numbers. For example, consider a function like this one:

-- |Moves pointer left, drawing a line
left :: (Convertible a Double) => a -> PathBuild ()
The logic being that I could perhaps take any input that would have an instance. This would let me create instances for say Int, Double, Float. But this would also let me create instances for newtype types that have an explicit unit.
For example:

newtype MM = MM Double
mm = MM

class Convertible a where
conv :: a -> Double

instance Convertible MM where
conv (MM n) = n

instance Convertible Int where
conv = realToFrac

left (mm 35) -- works
left 35 -- error!
The last entry wont work!

Ambiguous type variable `a0' in the constraints:
(Num a0) arising from the literal `1' at :0:6
(Conv a0) arising from a use of `left' at :0:1-4
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `left', namely `1'
In the expression: left 1
In an equation for `it': it = left 1
Why not? The message is quite explanatory, albeit cryptic.
To find out, lets fire up ghci and see what it thinks about the types of the last line.

GHCi, version 7.2.2: :? for help
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t left
left :: Conv a => a -> Double
*Main> :t 3
3 :: Num a => a
Aha! So ghc knows 3 is of type Num a, but cannot default to Int. That seems reasonable. We could have wildly different implementations of a typeclass for Int and Double (say for serializing them to a file) and when presented with a literal, ghc shouldn’t automagically choose some arbitrary type.
But it does exactly that today with Show!!

*Main> :t show
show :: Show a => a -> String
*Main> show 3
Whats going on! Looks like some typeclasses default to some instance, while others aren’t. The rules for the special defaulting in GHC can be found here.
Here’s a discussion about this topic on StackOverflow which explains why Show and Num play well together, but other “external” type classes don’t(i.e. they need the type to be explicitly specified).

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.