使用List.fold_right反转列表

时间:2014-01-22 07:06:11

标签: list ocaml

我刚刚开始学习ocaml,我目前遇到了一个问题,我希望使用[1;2;3]来反转列表(即[3;2;1]List.fold_right)。

从我到目前为止尝试过:

根据我的理解,

List.fold_right (fun x y -> x+y) [1;2;3] 0

将导致1+(2+(3+0))

所以我认为我可以通过

来反转列表
List.fold_right (fun x y -> y::x) [1;2;3] []

理论上哪个应该给我

1 swap (2 swap (3 swap []))进入1 swap ( [] 3 2),最终成为3 2 1

但是,这里似乎存在类型不匹配的问题?

此外,如果我要将功能更改为(fun x y -> y@x),我可以成功地将列表中的列表反转(即[[1];[2];[3]][[3];[2];[1]])。

这里发生了什么?

3 个答案:

答案 0 :(得分:1)

List.fold_right的类型为('a -> 'b -> 'b) -> 'a list -> 'b -> 'b。如果你看一下要折叠的函数的类型,它就是'a -> 'b -> 'b。换句话说,第一个参数是输入列表的新元素,第二个参数是累积的答案。在你的情况下,第一个参数是一个int(比如说),第二个参数是一个int列表。这就是您无法使用(fun x y -> y :: x)的原因。第一个参数x是下一个int(不是列表)。

如果你看一下你的示例表达式1 +(2 +(3 + 0)),这实际上是思考它的好方法,你会发现以这种方式反转列表是非常困难的。函数处理的第一个值应该位于结果的前面。这不是处理列表的自然方式。使用List.fold_left反转列表要容易得多(事实上,这很简单)。

如果您真的想这样做,您需要做的是将每个新值添加到累积结果的末尾。这不是不可能的,它只是一种处理列表的糟糕方式。这是一个向列表末尾添加值的函数:

let add_to_end x l = l @ [x]

答案 1 :(得分:1)

  

所以我认为我可以通过

来反转列表      

List.fold_right (fun x y -> y::x) [1;2;3] []理论上应该这样做   给我

     

1交换(2交换(3交换[]))到1交换([] 3 2)最终   变成3 2 1。

首先,在List.fold_right (fun x y -> y::x) [1;2;3] [],最初是y is []x is 3,您无法对此案例进行y::x,即您可以&#39 ; t []::3

交换是什么意思?

如其他答案所示,您必须提供append功能。

答案 2 :(得分:0)

您想要将列表项添加到累积列表的末尾。您通常只能在列表的头部操作,因此您不能使用cons(::)运算符。但是您可以将项目视为列表并将它们连接在一起(@)。只是两个操作数都需要是列表,所以将项目添加到列表中。

List.fold_right (fun x acc -> acc @ [x]) [1; 2; 3] []