我尝试了以下内容:
fun consAll (nil, n) = [n]
| consAll ((x::xs), n) = [[n::x], [consAll(xs, n)]];
但它会返回此错误:
"错误:操作员和操作数不同意[循环] 运营商域:' Z列表列表*' Z列表列表 操作数:' Z列表列表*' Z列表 表达式: ((n :: x):: nil)::(consAll(,):: nil):: nil"
请告诉我哪里出错了,我是SML的初学者。
答案 0 :(得分:3)
SML列表构造语法并不完全简单。由于我们使用[...]
来构造文字列表,因此我们很有可能认为我们也可以使用该符号来将列表和元素元素解构到列表的头部(例如,我们可以在Prolog中)。但是cons运算符::
只是一个中缀值构造函数,它接受类型'a
的项和类型'a list
的列表,并返回一个新的列表,其中项目是consed到头上的的清单。如果然后将结构的评估结果放在方括号中,那么现在已将结果列表包装在另一个列表中:
- 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
答案 1 :(得分:1)
[[n::x], [consAll(xs, n)]]
创建一个双元素列表,但您想要前置到列表中。请改用(n :: x) :: consAll(xs, n)
。