元组与列表非常不同。对于列表,大小不需要在编译时知道,但对于元组,不仅在编译时知道元素的数量,每个元素的类型都独立于其他元素。
取 的类型签名tl
:
- tl;
val it = fn : 'a list -> 'a list
它是'a list -> 'a list
- 换句话说,tl
接受一个并返回另一个。为什么我们没有一个用于元组的呢?假设我们想要类似的东西list
'a
y = (1,2,3);
tail y; (* returns (2,3) *)
为什么这没有意义?想想tail
. 那会是什么?在这种情况下,显然是
'a * 'b * 'c -> 'b * 'c
获取a 、 'a
a'b
和'c
a 的乘积并返回 a 和 a 的'b
乘积'c
。在 ML 中,定义的所有函数都必须具有静态确定的类型签名。不可能有一个处理所有可能的元组大小tail
的元组函数
,因为每个元组大小本质上是不同的类型。
'a list
可以是多种列表的类型:[1,2,3,4]
, or ["A", "short", "sentence"]
, or [true, false, false, true, false]。在所有这些情况下,类型变量的值'a
都绑定到不同的类型。(整数、字符串和布尔值)。并且'a list
可以是任意大小的列表。
但是采取元组:
(1, true, "yes"); (* (int * bool * string) *)
("two", 2) (* (string, int) *)
("ok", "two", 2) (* (string, string, int) *)
与列表不同,这些都是不同的类型。'a list
因此,虽然所有列表的类型签名都很简单(
所以你必须这样做:
y = (7, 8, 9);
(a, b, c) = y;
是你的头,a
你可以用 . 重新创建尾巴(b,c)
。或者创建自己的尾巴:
fun tail (a,b,c) = (b, c)
这也让我们直观地理解为什么这样的函数没有意义:如果不可能定义一个tail
用于所有元组类型的单一函数:
fun tail (a,b) = (b)
| tail (a,b,c) = (b, c) (* won't compile *)
您还可以使用#
速记来获取元组的某些元素:
#1 y; (* returns 7 *)
但请注意,这#1
不是函数,而是编译时的简写。