我刚刚开始学习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]]
)。
这里发生了什么?
答案 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] []