【发布时间】:2014-09-28 15:47:29
【问题描述】:
我正在尝试使用foldr 来反转如下列表
fun revl2 x = foldr(fn(x,y)=>y@[x],[]);
试试这个
fun revl1 x = foldr (op @) []x;
还有这个
fun revl1 x = foldr (op ::) []x;
它不起作用,我不知道为什么。
谢谢。
【问题讨论】:
标签: sml
我正在尝试使用foldr 来反转如下列表
fun revl2 x = foldr(fn(x,y)=>y@[x],[]);
试试这个
fun revl1 x = foldr (op @) []x;
还有这个
fun revl1 x = foldr (op ::) []x;
它不起作用,我不知道为什么。
谢谢。
【问题讨论】:
标签: sml
foldr 就是我们所说的柯里化函数。这意味着它不是将其参数作为一个元组,而是接受一个参数,然后返回另一个以相同方式接受其余参数的柯里化函数。在这种情况下,这意味着您需要将其称为foldr f init list,而不是foldr (f, init, list)。
这就是为什么您的第一次尝试是错误的(而且您根本没有提供 list 参数)。在您的第二次和第三次尝试中,您确实使用了正确的语法来调用它,但您不再提供正确的函数。
foldr 的函数有两个参数:列表的元素和累加器的当前值。在您的情况下,累加器是一个列表,因此您需要提供一个函数,其中第一个参数是列表的元素,第二个参数是列表。在您的第二次尝试中,您提供了 op @,它需要两个列表,所以这不起作用。
在您的第三次尝试中,您提供了op ::,它确实采用了一个元素和一个列表,但它在列表的开头添加了该元素。由于foldr (op ?) init xs 的结果是x1 ? x2 ? x3 ? ... ? xn ?? init,因此在这种情况下您会得到x1 :: x2 :: x3 :: ... :: xn :: [],这只是原始列表 - 没有任何内容被反转。
所以要解决这个问题,您需要提供一个在列表末尾添加单个元素的函数。这正是您第一次尝试的功能所做的,所以只需使用那个。
【讨论】:
foldr 具有签名('a * 'b -> 'b) -> 'b -> 'a list -> 'b 并被调用为:
foldr f init [x1, x2, ..., xn] 返回
f(x1, f(x2, ..., f(xn, init)...)) or init if the list is empty.
注意f 必须是一个接受两个参数的函数。由于您的函数的最终结果是一个列表,因此两个元素都必须是列表。
使用foldr 反转列表:
List.foldr (fn(x,y) => y @ [x]) [] [1,2,3]
将[] 放在参数x 周围会创建必要的列表。
【讨论】:
List.foldr 是来自 SML 基础库 [在我的答案中链接] 的完全限定名称 foldr。完全限定名称更可能适用于更广泛的特定 SML 安装,因此我出于习惯键入它。