[Hugs-users] overloading operators

Richard A. O'Keefe ok at cs.otago.ac.nz
Wed Apr 13 18:29:58 EDT 2005


Alfredo Paz-Valderrama <apaz at star.com.pe> wrote:
	but whe the Thompson's book says:
	
	--------------------------------------------
	Literals are not overloaded,

Here is what the Haskell 98 report says, in chapter 3 on page 18:

	An integer literal represents the application of the function
	fromInteger to the appropriate value of type Integer.  Similarly,
	a floating point literal stands for an application of fromRational
	to a value of type Rational (that is, Ratio Integer).

	+----------------------------------------------------------------+
	|Translation:  The integer literal i is equivalent to            |
	|fromInteger i, where fromInteger is a method in class Num (see  |
	|section 6.4.1).						 |
	|The floating point literal f is equivalent to fromRational (n   |
	|Ratio.% d), where fromRational is a method in class Fractional  |
	|and Ratio.% constructs a rational from two integers, as defined |
	|in the Ratio library.  The integers n and d are chosen so that  |
	|n/d = f.							 |
	+----------------------------------------------------------------+

In short, the Report clearly and explicitly says that literals *ARE*
overloaded!


	there is no automatic conversion from Int to Float.

But this is true.  There is no automatic conversion from Int to Float
*EXCEPT* for literals.

	.. we will receive an error message if we type
	
	(floor 5.6) + 6.7
	
note that the type of (floor 5.6) is not Int and
the type of 6.7 is not Float.

What we have is

    5.6 :: Fractional a => a
    floor :: (RealFrac a, Integral b) => a -> b
	Now RealFrac is a sub-type-class of Real and Fractional,
	so Fractional a & RealFrac a => RealFrac a and
	5.6 must belong to some instance of RealFrac.

	Here's where defaults come into play.  The Haskell98 report
	says in chapter 4 on page 52 that 
	    If no default declaration is given in a module,
	    then it is assumed to be
	    	default (Integer, Double)
	Basically, the default declaration says "if you can't figure
	out what some type variable is, and it must be an instance of
	at least one of the built-in numeric typeclasses, then pick
	the first type in this list that works."

	So in the absence of any 'default' decalaration of your own,
	(floor 5.6) is really
	((floor :: Integral b => Double -> b)
	 ((fromRational :: Ratio Integer -> Double)
	   (Ratio.% (56 :: Integer) (10 :: Integer)))) :: b
	and 5.6 counts as a Double (***not*** a Float).

    floor 5.6 :: Integral b => b
    6.7 :: Fractional c => c
    (+) :: Num d => d -> d -> d
	Now we have d = b and d = c, so we are looking for
	(+) :: Num d, Integral d, Fractional d => d -> d -> d

    But there is no type d which belongs to both Integral and Fractional.

    That is, there is NOT a clash between Int and Double,
    but a clash between "being an instance of Integral"
    and "being an instance of Fractional".

	since we are trying to add quantities of two different types.
	We have to convert the Int to a Float to perform the addtion, thus:
	
As noted above, according to the report, the default type for a
floating point literal is Double, not Float.

	fromIntegral (floor 5.6) + 6.7
	
	where fromInt takes int to corresponding Float.

Is fromInt a typo here?  There is no 'fromInt' in the Haskell report.

	sadly, if I use a integer number it's work!
	
	5 + 6.7
	
What's sad about that?  Wouldn't you want it to?

	WHY?????
	
Because literals *are* overloaded.  In *both* cases you need a call
to fromInteger to get the right type, but when it's an integer literal
the compiler inserts the call to fromInteger for you.

	5 is don't Integer like (floor 5.6)?
	
5 belongs to *every* numeric type.
(floor 5.6) belongs to *every* integral type.
So 5 belongs to every type that (floor 5.6) does AND MORE.


More information about the Hugs-Users mailing list