我有一个关于新泽西州 SML 解释列表的方式的问题:
假设我有一个函数 f(x : 'a, n : int) : 'a list
使得 f
返回 n
的列表x
的副本,例如f(2,5) = [2,2,2,2,2]
, f(9,0) = []
.
然后我进入 REPL,检查 f(9,0) = nil
,它返回真。由此,我假设您可以使用 list = nil
检查是否有 list
是空列表。我在一个函数中使用了它,但它无法运行。我最终了解到类型定义是不同的:
sml:121.2-123.10 Error: operator and operand don't agree [equality type required] operator domain: ''Z * ''Z
operand: 'a list * 'Y list
in expression:
xs = nil
(其中 xs 是我的列表)。然后我了解到检查列表是否为空列表的方法是使用
null list
.为什么会这样?怎么了 nil
?有人可以向我解释这种行为吗?我还注意到显然
(case xs = of nil
与检查 null xs
相同.这是否意味着 nil 是一种类型?
最佳答案
这是一个与多态相关的错误。默认情况下,当评估空列表时,它的类型为 'a list
.这意味着列表可以包含任何类型的元素。如果您尝试评估 1::[]
,因此您不会收到类型错误。这称为多态性,它是一种功能,允许您的函数采用任何类型的参数。这在 null
之类的函数中很有用,因为在这种情况下你不关心列表的内容,你只关心它的长度(实际上,你只关心它是否为空)。
但是,您也可以拥有不同类型的空列表。你可以让你的函数返回一个空的 int 列表。事实上,你正在你的函数中这样做。
这是您的函数的简单实现的结果:
- fun f(x : 'a, n : int) : 'a list =
case n of
0 => []
| _ => x::f(x, n-1);
val f = fn : 'a * int -> 'a list
- f(4,5);
val it = [4,4,4,4,4] : int list
- f(4,0);
val it = [] : int list
如您所见,即使第二个参数为 0,您的函数也会返回一个 int 列表。您应该能够直接将它与类型为
'a list
的列表进行比较。 .- it = [];
val it = true : bool
但是,如果您尝试比较具有不同类型且不是
'a list
类型的两个空列表。 ,你应该得到一个错误。你可以在下面看到一个例子:- [];
val it = [] : 'a list
- val list1 : int list = [];
val list1 = [] : int list
- val list2 : char list = [];
val list2 = [] : char list
- list1 = [];
val it = true : bool
- list2 = [];
val it = true : bool
- list1 = list2;
stdIn:6.1-6.14 Error: operator and operand don't agree [tycon mismatch]
operator domain: int list * int list
operand: int list * char list
in expression:
list1 = list2
另外,
case xs of nil
是一种检查列表是否为空的方法,但这是因为 nil
(这只是写 []
的一种方式)具有类型 'a list
默认情况下。 (注意 case 表达式不直接返回 bool 值。)因此,nil
不是类型,而是 'a list
是一种多态类型,您可以与任何类型的列表进行比较,但是如果您的空列表没有多态类型,则会出现类型错误,我认为您的情况会发生这种情况。
关于list - SML-NJ 列表等于 Nil 与 Null 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22977397/