Polymorphism
In OCaml, it might feel restrictive for functions to be strictly typed. For instance, we can't add floats with the plus function (+) because (+) only accepts ints.
While we are unable to write an addition function that accepts both ints and floats at the user's will in OCaml, there are times when we can write code/functions that does not assume a specific type, so we can use the same function with a multitude of types. This is called parametric polymorphism or just simply polymorphism. When we cover Object Oriented Programming, this idea may also be called generic programming.
Let's examine the following function that does not care what type of input it receives.
While we are unable to write an addition function that accepts both ints and floats at the user's will in OCaml, there are times when we can write code/functions that does not assume a specific type, so we can use the same function with a multitude of types. This is called parametric polymorphism or just simply polymorphism. When we cover Object Oriented Programming, this idea may also be called generic programming.
Let's examine the following function that does not care what type of input it receives.
let polymorphic any_input =
true
;;
val polymorphic : 'a -> bool = <fun>
The 'a (tick a) indicates that the function takes any type. From int lists to user defined types, this function will accept it. Let's look at another function that has multiple parameters.
let more_poly input1 input2 =
true
;;
val more_poly : 'a -> 'b -> bool = <fun>
We see that now we have a function that accepts 'a and 'b. These letters are different in order to indicate that the two inputs do not need to have the same type (both be ints or floats, etc.).
Let's see a function where both types, though they could be anything, should be the same.
Let's see a function where both types, though they could be anything, should be the same.
let more_limited_poly input1 input2 =
input1 = input2
;;
val more_limited_poly : 'a -> 'a -> bool = <fun>
'a and the rest are the most generic types for inputs. We can compromise between a super specific type and a completely generic type. For instance, we can indicate that our function only accepts lists, but what kind of list it takes doesn't matter.
Our function get_hd will get the head (first element) of the list and return it.
Our function get_hd will get the head (first element) of the list and return it.
let get_hd list =
match list with
| [] -> None
| frst :: _ -> Some frst
;;
val get_hd : 'a list -> 'a option = <fun>
Recall from above that the appearance of 'a in both the input and return value indicates that those types will be the same. For instance, if we give it an int list, the return value will be an int option.
This form of partially specific, partially generic typing comes in many forms, such as tuples that have one element generic and the other specific. If you don't tell OCaml to be specific, it will attempt to be as generic as possible.
So we've covered polymorphism as it applies to the type of functions we are writing currently. We see that we can write functions that don't care about what specific types they accept as inputs. We've seen that we can have generic lists and generic tuples, etc. We'll see polymorphism appear again when we hit OOP.