Is a multiple argument constructor ever useful over a single tuple argument constructor?

Viewed 61

For example, is there ever a case where a type like type x = A of int * int is better than type y = B of (int * int)? And what does this distinction actually mean?


The places I see that x is worse is trying to match the "argument" of the constructor (seems like it's two arguments, but its printed as one tuple) as a tuple:

type x = A of int * int
type y = B of (int * int)
              
let v = (1, 1)
(* let a = A v  (* Doesn't work *) *)
let b = B v  (* Works *)

(* let f = function
| A v -> v  (* Doesn't work *) *)
let g = function
| B v -> v  (* Works *)

So it looks like it only places restrictions to have multiple arguments, even though they have the same representation?

1 Answers

They don't have the same representation. The representation with the tuple takes more memory and it requires two objects rather than one.

A constructed value is represented by a header word, followed by one word for each value.

So A (x, y) is represented by 3 words: header, x, y.

And B ((x, y)) is represented by 2 words: header, tuple. Then tuple is represented by 3 words: header, x, y

Total for A is 3 words. Total for B is 5 words. Plus B has two objects to manage for GC and so on. Accessing the x component of A takes one indirection and for B it takes two indirections.

If you mean A (x, y) and B (x, y) look the same syntactically, that's true. It's definitely a little bit strange. But there is a point to having them be different internally (as I tried to show).

Related