Does interface belong to ad hoc polymorphism (i.e. overloading) or subtype polymorphism?

678 Views Asked by At

https://wiki.haskell.org/Polymorphism says

Ad-hoc polymorphism refers to when a value is able to adopt any one of several types because it, or a value it uses, has been given a separate definition for each of those types. For example, the + operator essentially does something entirely different when applied to floating-point values as compared to when applied to integers – in Python it can even be applied to strings as well. Most languages support at least some ad-hoc polymorphism, but in languages like C it is restricted to only built-in functions and types. Other languages like C++ allow programmers to provide their own overloading, supplying multiple definitions of a single function, to be disambiguated by the types of the arguments. In Haskell, this is achieved via the system of type classes and class instances.

Despite the similarity of the name, Haskell's type classes are quite different from the classes of most object-oriented languages. They have more in common with interfaces, in that they specify a series of methods or values by their type signature, to be implemented by an instance declaration.

Does it mean that type classes is a way to achieve overloading i.e. ad hoc polymorphism?

What kind of polymorphism does interface in OO languages (e.g. Java, C#) belong to, ad hoc polymorphism (i.e. overloading) or subtype polymorphism?

  • Since type class is similar to interface, is interface a way to achieve overloading i.e. ad hoc polymorphism, just as type class is?

  • Is interface similar to base class, so is interface a way to achieve subtype polymorphism, just as class inheritance is?

Thanks.

1

There are 1 best solutions below

2
On

Types has not type hierarchy, but Typeclasses has.

I wouldn't think about type classes as class inheritance, because you don't have the parent structure, you just have the signature. They may be seen as the classic interfaces of OOP languages, kind of...

But as the text you quoted says:

For example, the (+) operator essentially does something entirely different when applied to floating-point values as compared to when applied to integers

Something so simple as (+) function, with types are not so.

You have here a TypeClass hierarchy of Num to respect. For example

plus :: Num a => a -> a -> a
plus x y = x + y

and there you have (I can count) four direct subtypes Integral (implemented by Int and Integral) and Fractional (implemented by Float and Double). Integral and Fractional typeclasses are subtypes of Num typeclass.

so, look at this function type signatures:

(/) :: Fractional a => a -> a -> a

(div) :: Integral a => a -> a -> a

(+) :: Num a => a -> a -> a

each one of those has it's own implementation, and restricts the data type you can use in those type hierarchies of subtypes and supertypes, always talking about the Typeclass and not the type itself.

About the relation with OOP:

In Java by example, the Types and The classes are veeeeeeery different things. Look:

List<String> xs = new ArrayList<>();
List<String> ys = new LinkedList<>();
xs.add("Haskell");
ys.add("Forever");

The type there, is List, but the behavior of those lists is given by the Class (ArrayList or LinkedList). And even more, you can do:

ArrayList<String> ls = new ArrayList<>();
ls.add("something);

Is valid, the type and the class are the same.

On the other hand, in Haskell is not like that, the (+) method behavior is given by the implementation of the type according to its typeclass.

There is an example of a classic useful Typeclass hierarchy in Haskell:

Typeclass Hierarchy: