我对新泽西州SML解释清单的方式有疑问:
假设我有一个函数f(x : 'a, n : int) : 'a list
,f
会返回n
x
个f(2,5) = [2,2,2,2,2]
个副本的列表,例如f(9,0) = []
,f(9,0) = nil
。
然后我进入REPL,然后检查list = nil
,它返回true。由此,我假设您可以使用list
来检查null list
是否为空列表。我在一个函数中使用它,它不会运行。我最后得知类型定义不同:
sml:121.2-123.10错误:运算符和操作数不同意[需要相等类型] 运营商域名:'' Z *'' Z
操作数:'列表*' Y列表
在表达中:
xs = nil
(其中xs是我的清单)。然后我了解到检查列表是否为空列表的方法是使用nil
。为什么会这样? (case xs = of nil
发生了什么?有人可以向我解释这种行为吗?
我还注意到显然null xs
与检查{{1}}相同。这是否意味着nil是一种类型?
答案 0 :(得分:6)
这是与多态性相关的错误。默认情况下,在评估空列表时,它的类型为'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
(这只是一种编写[]
的方式)具有类型{{1 }} 默认情况下。 (请注意,case表达式不会直接返回布尔值。)因此,'a list
不是类型,但nil
是一种多态类型,可以与任何类型的列表进行比较,但是如果您的空列表没有多态类型,您将收到类型错误,我认为您的情况会发生什么。