使用ML作为编程语言,我们有列表和元组,在列表的情况下,我们可以通过从原始列表中删除或附加元素来形成另一个列表中的列表,例如,如果我们有:
val x = [7,8,9] : int list
在REPL中我们可以执行以下操作:
- hd x;
val it = 7 : int
- tl x;
val it = [8,9] : int list
现在如果我们有一个元组可以说:
val y = (7,8,9) :int*int*int
现在问题是,我们可以通过从原始元组中删除第一个元素来获得更小的元组吗?换句话说,如何删除(#1 y)
并使用新的元组(8,9)
,就像我们在列表中的情况一样。
感谢。
答案 0 :(得分:3)
元组与列表非常不同。对于列表,在编译时不需要知道大小,但是使用元组,不仅要在编译时知道元素的数量,每个元素的类型也独立于其他元素。
采用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
采用'b
,'c
和'b
的产品,并返回
一个'c
和一个tail
。在ML中,定义的所有函数必须具有静态确定
类型签名。那些元组的'a list
函数是不可能的
处理所有可能的元组大小,因为每个元组大小基本上是不同的类型。
[1,2,3,4]
可以是多种列表的类型:["A", "short", "sentence"]
或'a
,或
[true,false,false,true,false]。在所有这些情况下,类型的值
变量'a list
绑定到不同的类型。 (int,string和bool)。 (1, true, "yes"); (* (int * bool * string) *)
("two", 2) (* (string, int) *)
("ok", "two", 2) (* (string, string, int) *)
可以是任何大小的列表。
但是采取元组:
'a list
与list不同,这些都是不同的类型。因此,虽然所有列表的类型签名都很简单(y = (7, 8, 9);
(a, b, c) = y;
),但所有元组都没有“常见类型” - 2元组与3元组的类型不同。
所以你必须这样做:
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
但请注意{{1}}不是函数,而是编译时的简写。
答案 1 :(得分:1)
列表和元组是不可变的,所以不存在从它们中删除元素的事情。
您可以通过分解原始元组来构造新元组。在SML中,首选方法是使用模式匹配:
fun getLastTwo (x, y, z) = (y, z)
如果您喜欢#n
个功能,也可以使用它们:
val xyz = (7, 8, 9)
val yz = (#2 xyz, #3 xyz) (* (8, 9) *)