SML 如何将元素添加到列表列表中每个列表的开头?

SML How to prepend an element to the beginning of every list in a list of lists?

我尝试了以下方法:

fun consAll (nil, n) = [n]
  | consAll ((x::xs), n) = [[n::x], [consAll(xs, n)]];

但是returns这个错误:

"Error: operator and operand don't agree [circularity] operator domain: 'Z list list * 'Z list list list operand: 'Z list list * 'Z list list in expression: ((n :: x) :: nil) :: (consAll (,) :: nil) :: nil"

请告诉我哪里错了,我是SML的初学者。

[[n::x], [consAll(xs, n)]] 创建一个包含两个元素的列表,但您想要添加到列表中。请改用 (n :: x) :: consAll(xs, n)

SML 列表构造语法并不完全简单。由于我们使用 [...] 来构造文字列表,因此很容易认为我们也可以使用该符号来解构列表并将 cons 元素放到列表的头部(例如,在 Prolog 中)。但是 cons 运算符 :: 只是一个中缀值构造函数,它接受一个 'a 类型的项目和一个 'a list 类型的列表,并且 returns 是一个包含该项目的新列表conced 到列表的头部。如果您随后将评估此构造的结果括在方括号中,则您现在已将结果列表包装在另一个列表中:

- 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]

这表示,如果列表列表为空,则 return 包含要在每个列表中使用的项目的单例列表。但是你正在定义一个函数,它应该 cons n 到每个列表的头部,它是第一个参数中列表的成员。当您 运行 超出第一个参数中的列表时,您应该 return 一个空列表,因为没有更多的列表可供使用。有道理吗?

这里有两种写法你描述的函数。一个使用简单递归,另一个使用高阶函数 List.map:

fun consAll ([], _) = []
  | consAll ((x::xs), n) = (n::x) :: consAll(xs, n)

fun mapCons x lists = List.map (fn ls => x :: ls) lists