Parametric polymorphism is a programming language feature to provide compile time polymorphism, Parametric Polymorphism is better know as Generics, a function using generics can be made to handle any time of data regardless its type while maintaining static type correctness.

Lets consider the following example:

protocol Speaking {
  typealias Voice
  func speak () -> Voice

class Dog : Speaking {
  func speak() -> String {
    return "BARK!"

class Cat : Speaking {
  func speak() -> [String] {
    return ["Meooww", "Meooww"]

Both Cat and Dog are implementing the Speaking protocol, they return different type from their speak function. Lets write a function that calls the Speakers:

func call(speaker: Cat) -> [String] {
  return speaker.speak()

func call(speaker: Dog) -> String {
  return speaker.speak()

Since swift is a statically typed language we need to have two different method, lets try to solve the above using subtype polymorphism.

func speak(speaker: Speaking) -> Speaking.Voice {
  return speaker.speak()

The above looks like the right solution but sadly it does not compile, in swift a Protocol that uses an Associated Type cannot be used as a type of a function parameter, in fact this type of protocol can only be used in generics.

Lets solve the above problem using generics, we can rewrite the above as:

func speak<T: Speaking>(speaker: T) -> T.Voice {
  return speaker.speak()

We defined a function that takes in a type that implements Speaker and return A Voice (the associated type with Speaker), We can now call it with Dogs and Cats:

println(call(Dog())) //prints BARK!
println(call(Cat())) //prints [Meooww, Meooww]

Using generics we were able to get rid of the specialized methods and create one method that takes a Generic value.

Generic calls are decided at compile type, hence the name of compile time polymorphism, when provided with multiple generic function, the compiler will select the appropriate one.

A good example for that is the lazy swift function, swift declares the following copies of lazy:

func lazy<S : CollectionType where S.Index : ForwardIndexType>(s: S) -> LazyForwardCollection<S>
func lazy<S : CollectionType where S.Index : BidirectionalIndexType>(s: S) -> LazyBidirectionalCollection<S>
func lazy<S : CollectionType where S.Index : RandomAccessIndexType>(s: S) -> LazyRandomAccessCollection<S>
func lazy<S : SequenceType>(s: S) -> LazySequence<S>

Lazy function is overloaded 4 times, the compiler will deduct which lazy function to call, the decision of which function to call will be based on what the generic is implementing and on what it declares as its associate type:


In the above example the compiler will chose the lazy function that returns the LazyRandomAccessCollection since the IndexType of the array is RandomAccessIndexType

Lets override our call function to experiment with static polymorphism:

func call<T: Speaking where T.Voice == Array<String>>(speaker: T) -> T.Voice {
  return ["Don't wanna speak!"]

func call<T: Speaking where T.Voice == String>(speaker: T) -> T.Voice {
  return speaker.speak()

The compiler should be able to decide which method to call basing on the protocol associated type:

var s = call(Dog())

Since Dog associate type is String the compiler should be able to select the second function, however, the following will not compile due to Ambiguous use of 'call', this seems to be a bug with swift since passing Dog should be enough for the compiler to select the correct function

We can work around the above issue by annotating the return variable:

var s: String = call(Dog())

It seems that swift is just using function overloading to select the correct function to call from the return value, the compiler is disregarding the parameter passed to it, it is not taking in consideration where T.Voice == String, so the following call will compile too:

var s: String = call(Cat())

We passed Cat which Voice of [String] and received the result in a String variable, this will result in a run time exception.

The compiler however can correctly decide which function to call if we check the associated type conformance to a protocol, swift can correctly understand S.Index : BidirectionalIndexType and S.Index : RandomAccessIndexType but not S.Index == Int (bug?).

It seems that swift compiler still has some issues around generics and the correct use of Protocol associated types.