Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Haskell have return type overloading?

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
like image 557
Laurence Gonsalves Avatar asked Jul 10 '12 19:07

Laurence Gonsalves


People also ask

Does Haskell support overloading?

Haskell's type class mechanism supports composability in two dimensions. First, it allows users to de- fine overloaded functions from other overloaded functions, and second, it allows compound instances to be defined from simpler instances.

Does Haskell have return?

return is actually just a simple function in Haskell. It does not return something. It wraps a value into a monad. Looks like return is an overloaded function.

Does Haskell have polymorphism?

Polymorphism is widespread in Haskell and is a key feature of its type system. Most polymorphism in Haskell falls into one of two broad categories: parametric polymorphism and ad-hoc polymorphism.

Can a Haskell function return nothing?

No. However, you can have functions that return a trivial value. The () type has only one inhabitant, () .


2 Answers

Well, one way to look at it is that Haskell translates the return type polymorphism that you're thinking of into parametric polymorphism, using something called the dictionary-passing translation for type classes. (Though this is not the only way to implement type classes or reason about them; it's just the most popular.)

Basically, fromInteger has this type in Haskell:

fromInteger :: Num a => Integer -> a

That might be translated internally into something like this:

fromInteger# :: NumDictionary# a -> Integer -> a
fromInteger# NumDictionary# { fromInteger = method } x = method x

data NumDictionary# a = NumDictionary# { ...
                                       , fromInteger :: Integer -> a
                                       , ... }

So for each concrete type T with a Num instance, there's a NumDictionary# T value that contains a function fromInteger :: Integer -> T, and all code that uses the Num type class is translated into code that takes a dictionary as the argument.

like image 125
Luis Casillas Avatar answered Sep 30 '22 05:09

Luis Casillas


The seminal paper on Haskell-style typeclasses is called "How to make ad-hoc polymorphism less ad hoc". So, the answer to your question is a qualified "yes" -- depending on just how ad hoc you require your return-type overloading to be...

In other words: there is no question that ad hoc polymorphism is relevant to typeclasses, since that was a motivating example for inventing them. But whether you think the result still qualifies as "return-type overloading" depends on the fiddly details of your favored definition.

like image 38
comingstorm Avatar answered Sep 30 '22 04:09

comingstorm