Tuples are very different from lists. With lists, size need not be known at compile time, but with tuples, not only should the number of elements be known at compile time, the type of each element is independent of the others.
Take the type signature of tl
:
- tl;
val it = fn : 'a list -> 'a list
It is 'a list -> 'a list
- in other words tl
takes a list
of 'a
and returns another one. Why don't we have one for tuples as well? Assume we wanted something like
y = (1,2,3);
tail y; (* returns (2,3) *)
Why does this not make sense? Think of the type signature of tail
. What would it be?
In this case, it would clearly be
'a * 'b * 'c -> 'b * 'c
Takes product of an 'a
, a 'b
and a 'c
and returns a product of
a 'b
and a 'c
. In ML, all functions defined must have a statically determined
type signature. It would be impossible to have a tail
function for tuples that
handles all possible tuple sizes, because each tuple size is essentially a different type.
'a list
Can be the type of many kinds of lists: [1,2,3,4]
, or ["A", "short", "sentence"]
, or
[true, false, false, true, false]. In all these cases, the value of the type
variable 'a
is bound to a different type. (int, string, and bool). And 'a list
can be a list of any size.
But take tuples:
(1, true, "yes"); (* (int * bool * string) *)
("two", 2) (* (string, int) *)
("ok", "two", 2) (* (string, string, int) *)
Unlike list, these are all of different types. So while the type signature of all lists is simple ('a list
), there is no 'common type' for all tuples - a 2-tuple has a different type from a 3-tuple.
So you'll have to do this instead:
y = (7, 8, 9);
(a, b, c) = y;
and a
is your head and you can re-create the tail with (b,c)
.
Or create your own tail:
fun tail (a,b,c) = (b, c)
This also gives us an intuitive understanding as to why such a function would not make sense: If is impossible to define a single tail
for use across all tuple types:
fun tail (a,b) = (b)
| tail (a,b,c) = (b, c) (* won't compile *)
You can also use the #
shorthand to get at certain elements of the tuple:
#1 y; (* returns 7 *)
But note that #1
is not a function but a compile time shorthand.