SML 列表构造语法并不完全简单。由于我们使用[...] 来构造文字列表,因此很容易认为我们也可以使用该符号来解构列表并将 cons 元素放在列表的头部(例如,在 Prolog 中)。但是 cons 运算符 :: 只是一个中缀值构造函数,它接受 'a 类型的项目和 'a list 类型的列表,并返回一个新列表,其中包含在列表头部的项目。如果您随后将评估此构造的结果括在方括号中,则您现在已将结果列表包装在另一个列表中:
- val xs = [2,3,4];
val xs = [2,3,4] : int list
- [1::xs];
val it = [[1,2,3,4]] : int list list
您的定义中还有两个额外的错误:
首先,当您的意思是在第二个受保护函数定义的主体中将头放在列表的尾部时,您正在创建一个包含两项的列表。
第二,你的基地不正确:
fun consAll (nil, n) = [n]
这就是说,如果列表列表为空,则返回一个单例列表,其中包含要包含在每个列表中的项目。但是您正在定义一个函数,该函数应该将n 放在每个列表的头部,该列表是第一个参数中列表的成员。当您在第一个参数中用完列表时,您应该只返回一个空列表,因为没有更多的列表可供使用。有意义吗?
这里有两种写你描述的函数的方法。一个使用简单递归,另一个使用高阶函数List.map:
fun consAll ([], _) = []
| consAll ((x::xs), n) = (n::x) :: consAll(xs, n)
fun mapCons x lists = List.map (fn ls => x :: ls) lists