Based on what I've read about Haskell, and the experimentation I've done with GHC, it seems like Haskell has return type overloading (aka ad hoc polymorphism). One example of this is the fromInteger
function which can give you a Double
or an Integer
depending on where the result is used. For example:
fd :: Double -> String
fd x = "Double"
fi :: Integer -> String
fi x = "Integer"
fd (fromInteger 5) -- returns "Double"
fi (fromInteger 5) -- returns "Integer"
A Gentle Introduction to Haskell seems to agree with this when it says:
The kind of polymorphism that we have talked about so far is commonly called parametric polymorphism. There is another kind called ad hoc polymorphism, better known as overloading. Here are some examples of ad hoc polymorphism:
- The literals 1, 2, etc. are often used to represent both fixed and arbitrary precision integers.
If the numeric literals are considered to be an example of ad hoc polymorphism (aka overloading), then it seems that the same is true for the result of functions like fromInteger
.
And in fact, I've found some answers to other questions on Stack Overflow that suggest that Haskell has overloading by return type.
However, at least one Haskell programmer has told me that this isn't return type overloading, and is instead an example of "parametric polymorphism, where the parameter is bound by a universal quantifier".
I think what he's getting at is that fromInteger
is returning a value from every instance of Num
(sort of a nondeterministic type).
That seems like a reasonable interpretation, but as far as I can tell, Haskell never lets us look at more than one of these instance values (thanks in part to the Monomorphism restriction). It also seems like the actual instance who's value we look at can be determined statically. Because of all of this, it seems reasonable to say that in the expression fd (fromInteger 5)
the subexpression fromInteger 5
is of type Double
, while in the expression fi (fromInteger 5)
the subexpression fromInteger 5
is of type Integer
.
So, does Haskell have return type overloading?
If not, please provide an example of one of the following:
- valid Haskell code that would have different behavior if Haskell had return type overloading
- valid Haskell code that would be invalid if Haskell had return type overloading
- invalid Haskell code that would be valid if Haskell had return type overloading
Num a => a
is parametric polymorphism then I'd expectNum a =>
would mean "the type ofa
is some instance ofNum
, you can't rely on which". It would only let you perform operations that applied to all instances ofNum
, but Haskell lets you perform operations on aNum a => a
that only apply to specific instance ofNum
. You can depend on their type. – Laurence GonsalvesfromInteger
where the result can be given to both a function that accepts onlyInteger
and also to one that accepts onlyDouble
(modulo whatever the types in ML are called). This suggests that either Haskell has a more powerful form of parametric polymorphism, or that the difference is not coming from parametric polymorphism. – Laurence Gonsalves