You're looking at this wrong (though I won't blame you: it's pretty surprising at first). It may seem to you that constructors follow the syntax Name of type
where the type part follows normal type syntax (which lets it contain tuples).
In reality, tuples and constructors follow the exact same syntax: a constructor is merely a tuple with a name in front of it:
tuple/constructor == [name of] type [* type] [* type] ...
So, the *
in a constructor definition are not part of the tuple syntax, they're part of the constructor syntax. You're literally defining a constructor as being this name, followed by N arguments as opposed to this name, followed by an argument which is a tuple.
The reason behind this subtle difference in behavior is one of performance. Right now, tuples and constructors are represented in memory as such:
[TYPE] [POINTER] [POINTER] [POINTER]
This is a fairly compact and efficient representation. If the multiple arguments of a constructor could indeed be accessed as a tuple, this would require the runtime to represent that tuple independently from the constructor (in order for it to be independently addressable) and so it would look like this:
[TYPE] [POINTER]
|
v
[TYPE] [POINTER] [POINTER] [POINTER]
This would use marginally more memory, require twice as many allocations when using a constructor, and reduce the performance of pattern-matching tuples (because of an additional dereference). In order to retain maximum performance, the name of type * type
is represented using the first pattern, and you need to explicitly type name of (type * type)
to cut off the *
from the of
and thus fall back on the second pattern.
Note that both patterns are accessed through the same pattern-matching and construction syntax: name (arg,arg)
. This means that type inference cannot deduce the pattern based on usage. This is no problem for normal constructors, which are always defined in a type definition, but it causes variants (which need no preliminary definition) to automatically fall back on the second version.
Additional reading on the memory representation of types here.