感谢jacobm的帮助,我想出了一个解决方案。
// Folding Recursion
let reverse_list_3 theList =
List.fold_left (fun element recursive_call -> recursive_call::element) [] theList;;
我正在学习OCaml中的不同递归方式(对于类)和一些练习,我正在编写一个函数来使用不同的递归样式来反转列表。
// Forward Recursion
let rec reverse_list_forward theList =
match theList with [] -> [] | (head::tail) -> (reverse_list_1 tail) @ [head];;
// Tail Recursion
let rec reverse_list_tail theList result =
match theList with [] -> result | (head::tail) -> reverse_list_2 tail (head::result);;
现在,我正在尝试使用List.fold_left
编写反向函数,但我陷入了困境,无法弄明白。如何使用折叠编写这个反向函数?
另外,如果有人对函数式编程有很好的引用,不同类型的递归,高阶函数等等,链接将不胜感激:)
答案 0 :(得分:8)
我觉得将折叠操作看作是对操作序列做什么的概括很有帮助
a + b + c + d + e
fold_right (+) 0
使用+
作为基本情况,以关联方式应用0
操作:
(a + (b + (c + (d + (e + 0)))))
fold_left 0 (+)
以左关联方式应用它:
(((((0 + a) + b) + c) + d) + e)
现在考虑一下,如果您将+
替换为::
,将0
替换为[]
,则会在右侧和左侧折叠中发生。
考虑fold_left
和fold_right
作为“替换”列表中的::
和[]
运算符的方式也可能很有用。例如,列表[1,2,3,4,5]
实际上只是1::(2::(3::(4::(5::[]))))
的简写。将fold_right op base
视为让::
替换op
而[]
替换为base
可能会有用:例如
fold_right (+) 0 1::(2::(3::(4::(5::[]))))
变为
1 + (2 + (3 + (4 + (5 + 0))))
::
成为+
,[]
成为0
。从这个角度来看,很容易看到fold_right (::) []
只是让你回到原来的列表。 fold_left base op
做了一些奇怪的事情:它重写了列表周围的所有括号以转向另一个方向,将[]
从列表后面移到前面,然后然后将::
替换为op
,将[]
替换为base
。例如:
fold_left 0 (+) 1::(2::(3::(4::(5::[]))))
变为
(((((0 + 1) + 2) + 3) + 4) + 5)
使用+
和0
,fold_left
和fold_right
会产生相同的结果。但在其他情况下,情况并非如此:例如,如果您使用+
代替-
,结果会有所不同:1 - (2 - (3 - (4 - (5 - 0))) )= 3,但是(((((0 - 1) - 2) - 3) - 4) - 5)= - 15.
答案 1 :(得分:0)
let rev =
List.fold_left ( fun lrev b ->
b::lrev
) [];;
测试:
# rev [1;2;3;4];;
- : int list = [4; 3; 2; 1]