Note that the difference between Foo of (a * b)
and Foo of a * b
exists for efficiency reasons: Foo of (a * b)
has an argument, which is a tuple, a pointer to two elements on the heap. Foo of a * b
has two arguments that are directly packaged with a tag, avoiding indirection.
This is also the reason that, for example, algorithms using association lists (e.g. Hashtables with associated buckets) sometimes define their own data type instead of reusing ('a * 'b) list
:
type ('a, 'b) assoc_list = | Nil | Cons of 'a * 'b * ('a, 'b) assoc_list
Of course, in the general case at a high level, such specializations are not very important (and can prevent code reuse), but it’s nice to be able to go to such technical details when you really need more tight control over the memory representation.
source share