# type foo = Foo of int * int
# let t = (1, 2)
# Foo t
Error: The constructor Foo expects 2 argument(s),
but is applied here to 1 argument(s)
How is it that I must do Foo (1, 2)
to avoid that error even t has the appropriate type?
This is one of the troubling parts of OCaml syntax, in my opinion. Despite the way it looks, the constructor Foo doesn't require a 2-tuple as its argument. It requires, syntactically, two values in parentheses--but they aren't a tuple. So it's simply the case that t
has the wrong type. The way to make this work is to say:
let (a, b) = t in Foo (a, b)
The problem really is that parentheses are being used for two different things (or so I claim). Once you get used to this it's not so difficult to deal with.
Edit: if you want the constructor Foo to take a single tuple, rather than two separate values, you can define it like this:
type foo = Foo of (int * int)
Then the rest of your original code will work.
Note that the distinction between Foo of (a * b)
and Foo of a * b
is there for efficiency reasons: Foo of (a * b)
has an argument which is a tuple, a pointer to two elements in the heap. Foo of a * b
has two arguments that are directly packed with the tag, avoiding an indirection.
This is also the reason why, for example, algorithms that use association lists (for examples Hashtables with linked list buckets) sometimes define their own datatype 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 high-level case such specializations are not terribly important (and can hinder code reuse), but it's still nice to be able to get down to such technical details when you actually need tighter control over memory representation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With