The Two Polymorphisms

I was thinking about why Go doesn’t, and shouldn’t, have generics. Then it dawned on me: there are two styles of polymorphism.

The first would be that associated with languages such as Java, C#, Haskell, etc. These are languages with generics or something similar which allow you to define types such as List<int>, Dictionary<string, Thing> and so on, with methods/functions that act on a genericList<T>. This I think of as structural polymorphism since it is determining what to do based on the structure of a value.

The other style would instead be associated with Go, Ruby, Smalltalk, etc. These are languages with a way of determining whether an object has a particular behaviour, either by querying its methods (Ruby respond_to?, Smalltalk respondsTo) or by defining an implicit interface as in Go. This would be behavioural polymorphism since it determines what to do based on the behaviour of a value.

Each style is suited to solving different problems, but neither could be argued to be more powerful than the other.

I can’t think of a language that supports both styles, but there is a theme. The dynamic languages favour a behavioural approach, since they have no good way to represent the type information required for a structural approach; and the statically typed languages favour a structural approach for the inverse reason, they are tied to the idea of types as structure.

Go then is the outlier. It is statically typed, yet has a behavioural style of polymorphism. Perhaps this is the reason the Go authors haven’t shown any enthusiasm to including something like generics, they have already chosen their preferred polymorphism.