Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example of "True Polymorphism"? (Preferably, using Haskell) [closed]

I've seen lots of partial definitions of "True Polymorphism", for example here and here but nowhere have I been able to find a clear example of the difference with two concrete examples.

I understand that overloading the + operator is some form of polymorphism and that it is implemented differently in Haskell and C++. Can someone show precisely what the difference is with examples in both languages?

like image 285
CodyBugstein Avatar asked Jan 14 '23 12:01

CodyBugstein


2 Answers

The term you are looking for is "parametric polymorphism", which is different from "ad-hoc polymorphism".

An example of parametric polymorphism is in the type signature for Nothing:

Nothing :: Maybe a

The a in the type could be any conceivable type, since Nothing inhabits all Maybes. We say that a is parametrically polymorphic because it can be any type.

Now consider this type:

Just 1 :: (Num b) => Maybe b

This time the b cannot be any type: it can only be a type that is an instance of Num. We say that b is ad-hoc polymorphic because it can be any member of a set of types, given by the instances of the Num class.

So, to recap:

  • Parametric polymorphism: Can be any type

  • Ad-hoc polymorphism: Constrained by a type-class

like image 194
Gabriella Gonzalez Avatar answered Jan 16 '23 02:01

Gabriella Gonzalez


There are three types of polymorphism you'll encounter frequently ( with C++ and Haskell examples ).

Parametric polymorphism in functional languages is a feature of type systems where the type of a function is an expression quantified over type variables. The input types constrain free parameters in signature which determines the output type. For example the map function takes a function as its first argument which determines the type of the input list and the output list.

map :: (a -> b) -> [a] -> [b]

In type theory parlance the signature is often written:

 ∀ a. ∀ b. (a -> b) -> [a] -> [b]

C++ can achieve the effects of parametric polymorphism through templates, but is in my opinion very brittle ( i.e. leads to vague compile errors ) and lacks the formalism found in found functional languages:

template <class T>
T add(T a, T b) {
    return a+b;
}

Ad-hoc polymorphism is when functions with the same name act differently when "viewed" with different type signatures. In Haskell this is expressed with type classes. The type a in signature for (+) is bounded to types which implement the Num type class.

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

class Num a where
    (+) :: a -> a -> a

instance Num Int  where
    (+) = plusInt 

Subtype polymorphism. Not present in Haskell but other languages ( Scala, ML ) have subtype polymorphism. In object oriented languages this is usually a language feature where different object instances implement a method or property calls with the same name and are dispatched depending on the semantics of the object model. In C++ for example:

class Animal {
public:
 virtual void speak() = 0;
};

class Cat : public Animal {
public:
 void speak() { 
    printf("Meow");
 }
};

class Dog : public Animal {
public:
 void speak() { 
    printf("Woof");
 }
};

The thing to remember about polymorphism is to separate the core idea from the implementation. For example, ad-hoc polymorphism is not the same as type-classes, it's just one expression of it.

like image 26
Stephen Diehl Avatar answered Jan 16 '23 01:01

Stephen Diehl