Search code examples
genericsocamlprogramming-languagescomputer-science

Which language's generics are generic classes and functions in OCaml similar to, C++, Java or C#?


I learned the difference between C++ templates, Java generics and C# generics from https://stackoverflow.com/a/31876747/3284469, which help me better understand how to use them correctly in different ways.

Classes in OCaml can also have type parameters, see "Class Parameters and Polymorphism" in https://realworldocaml.org/v1/en/html/classes.html.

If I am correct, in OCaml, while classes can be made explicitly parametric polymorphism, functions implicitly parametric polymorphism?

To help me learn to use generics in OCaml, which language's generics are generic classes and functions in OCaml similar to, C++, Java or C#? Am I correct that because OCaml's functions are made implicit parametric polymorphic instead of explicitly, and the generic functions in C++, Java and C# are explicitly parametric polymorphic, they are in no way similar?

OCaml seems to have a third generics: generic modules called functors. If I am correct, generic modules are different from generic classes and functions in OCaml. My questions here are only about classes and functions.

Thanks.


Solution

  • TL;DR; Java is the closest.

    OCaml type system provides parametric polymorphism, that means that a type of value can have type variables (parameters), meaning that a value can have multiple types in a given context. Unlike languages that you mentioned, OCaml also has type inference. OCaml will infer the most general type of value, based on how the value is used in a program, i.e., it will try to find the biggest set of types that match the usage of the value. The property of a type inference system to be able to derive the most general type (the biggest set of types - also called the principal type), is called principality. OCaml uses a type-inference system that is based on Hindley-Milner type system, though it went much father. First of all, OCaml has subtyping, and type inference (that tries to be principal) with subtyping requires some help from a programmer in a form of annotations (otherwise it will infer less general types). This is why OCaml classes have explicit type parameters. If we will forget about subtyping, then classes, objects, functions, and even functors can be considered equal. In fact, they basically have the same runtime representation. In OCaml, we do not make a difference between explicit and implicit type variables. A type of function also have type variables, but since the compiler usually infers the type for us we do not specify them. However, when we define module interfaces, we always explicitly specify type variables, for example, consider the List module that provides the length function that has type 'a list -> int. As you may see, the type variable 'a is quite explicit here.

    Concerning the representation, the Java representation is a correct way of implementing parametric polymorphism. As parametric polymorphism speaks about one value, that has multiple types, not a family of values with different types (it doesn't matter whether they are constructed either at runtime or compile time). This shows an essential difference between C#/C++ generics and OCaml/Java generics. In the latter, we have a value that is generic, while in the former we have a factory of values that has the same interface, but may have different implementations, that is actually an example of ad hoc polymophism. So, in OCaml, when you have a polymorphic function or a data value, it is always only one object, no matter where it is applied, e.g., in List.length [1;2;3] and List.length ["hello"; "world"] the same code of the List.length function is applied to different lists.