Polymorphism in Elixir
Polymorphism is the provision of a single interface to entities of different types. Basically, it allows different data types respond to same function. So the same function shapes for different data types to accomplish the same behaviour. Elixir language has ‘protocols’ to implement polymorphism with a clean way.
Lets implement a basic protocol that convert Kelvin and Fahrenheit temperatures to Celsius.
defmodule Kelvin do
defstruct name: "Kelvin", symbol: "K", degree: 0
enddefmodule Fahrenheit do
defstruct name: "Fahrenheit", symbol: "°F", degree: 0
enddefmodule Celsius do
defstruct name: "Celsius", symbol: "°C", degree: 0
enddefprotocol Temperature do
@doc """
Convert Kelvin and Fahrenheit to Celsius degree
"""
def to_celsius(degree)
enddefimpl Temperature, for: Kelvin do
@doc """
Deduct 273.15
"""
def to_celsius(kelvin) do
celsius_degree = kelvin.degree - 273.15
%Celsius{degree: celsius_degree}
end
enddefimpl Temperature, for: Fahrenheit do
@doc """
Deduct 32, then multiply by 5, then divide by 9
"""
def to_celsius(fahrenheit) do
celsius_degree = (fahrenheit.degree - 32) * 5 / 9
%Celsius{degree: celsius_degree}
end
end
Now, we implemented our converters for the Kelvin and Fahrenheit types. Lets make some conversions:
iex> fahrenheit = %Fahrenheit{degree: 45}
%Fahrenheit{degree: 45, name: "Fahrenheit", symbol: "°F"}
iex> celsius = Temperature.to_celsius(fahrenheit)
%Celsius{degree: 7.22, name: "Celsius", symbol: "°C"}iex> kelvin = %Kelvin{degree: 300}
%Kelvin{degree: 300, name: "Kelvin", symbol: "K"}
iex> celsius = Temperature.to_celsius(kelvin)
%Celsius{degree: 26.85, name: "Celsius", symbol: "°C"}
Lets try to convert any other data type which has no implementation for to_celsius function:
iex> Temperature.to_celsius(%{degree: 12})
** (Protocol.UndefinedError) protocol Temperature not implemented for %{degree: 12}
iex:11: Temperature.impl_for!/1
iex:15: Temperature.to_celsius/1
If you want to cover all data types you can define an implementation for Any data type. Lastly, if you have time, check source code of ‘Enum’ and ‘String.Char’, which are good examples of polymorphism in core Elixir.
Happy functional coding with ♥!