[Haskell-beginners] Type ambiguity - Int vs. Integer

Andres Loeh andres at cs.uu.nl
Mon May 17 13:43:32 EDT 2010


Hi.

So this fragment works:

> data AW = AI Integer deriving (Show, Eq, Ord)
>
> class AWC a where
>     toAW :: a -> AW
>     fromAW :: AW -> a
>
> instance AWC Integer where
>     toAW 		= AI
>     fromAW (AI v) 	= v
>
> > toAW 5
> 5

But replacing Integer by Int everywhere above
yields

> > toAW 5
> Ambiguous type variable 't' in the constraints:
>   'Num t' arising from the literal '5'
>   'AWC t' arising from the use of 'toAW'

The reason for this behaviour is a dark(er) corner of Haskell called
"defaulting", described in Section 4.3.4 of the Haskell Report. Look at
what ghci says about 5:

> :t 5
5 :: (Num t) => t

So, the literal 5 can be interpreted as any numeric type. This is
nice, because it allows us to use 5 as an integer, as in

> :t length [] + 5
length [] + 5 :: Int

or as a floating point number

> :t sin pi + 5
sin pi + 5 :: (Floating a) => a

(Note that the latter type is still overloaded, as Floating can
be instantiated to either Float or Double.)

Now, your method toAW has the type

(AWC a) => a -> AW

You apply this method not to a value of a specific type, but to
a value of another overloaded type, namely your literal 5. This
means that Haskell has to figure out which concrete type to choose
for "a" in this case.

Haskell's type classes are open, and it usually does not randomly
pick one if multiple *might* match. In this case, there is an instance
for Integer (in your first example) or Int (in your second), but there
might as well be another one for Float or Double. Which one would be
the right one? Well, as I said, usually Haskell is conservative here
and just complains, hence the "Ambiguous type variable" error you get
in the second case.

However, there is a mechanism in Haskell to give heuristics, and
that's what "defaulting" is all about. Under normal circumstances,
Haskell will, for numeric types, pick "Integer" in cases of ambiguity,
and if that doesn't work, it will try "Double". It does not try "Int"
though. This explains why your first example (by accident) works.

If you ask GHCi for the type, defaulting isn't applied, but you
can observe it to happen in many places. For example,

> show 5
"5"

> show (5 :: Double)
"5.0"

So, apparently, Haskell decides to show an unconstrained numeral
like an Integer, not like a Double.

A more conclusive example is

> Data.Typeable.typeOf 5
Integer

Defaulting to Double if Integer is ruled out can be observed by

> Data.Typeable.typeOf (sin pi)
Double

Cheers,
  Andres

-- 

Andres Loeh, Universiteit Utrecht

mailto:andres at cs.uu.nl     mailto:mail at andres-loeh.de
http://www.andres-loeh.de


More information about the Beginners mailing list