使用fold_left/right反转OCaml中的列表
更新 - 解决方案
感谢 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 编写一个反向函数,但我陷入困境并且无法弄清楚。我如何使用折叠来编写这个反向函数?
另外,如果有人对函数式编程、不同类型的递归、高阶函数等有很好的参考,链接将不胜感激:)
UPDATE - Solution
Thanks to jacobm for his help, I came up with a solution.
// Folding Recursion
let reverse_list_3 theList =
List.fold_left (fun element recursive_call -> recursive_call::element) [] theList;;
I'm learning about the different ways of recursion in OCaml (for class) and for some exercise, I'm writing a function to reverse a list using different recursion styles.
// 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);;
Now, I'm trying to write a reverse function using List.fold_left
but I'm stuck and can't figure it out. How would I write this reverse function using folding?
Also, if anyone has good references on functional programming, the different types of recursion, higher-order-functions, etc..., links would be greatly appreciated :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现将折叠操作视为对一系列操作的概括是有帮助的
fold_right (+) 0
右关联地应用+
操作,使用0
作为基本情况:fold_left 0 (+)
将其左关联应用:现在考虑如果将
+
替换为会发生什么::
和0
与[]
位于右折叠和左折叠中。考虑一下
fold_left
和fold_right
的工作方式“替换”::
和[] 列表中的运算符。例如,列表
[1,2,3,4,5]
实际上只是1::(2::(3::(4::(5:: []))))
。将fold_right op base
视为让您用op
和[]::
可能会很有用> 与base
:例如变为
::
变为+
,[]
变为0
>。从这个角度来看,很容易看出fold_right (::) []
只是返回原始列表。fold_left base op
做了一些有点奇怪的事情:它重写列表周围的所有括号以向另一个方向移动,将[]
从列表的后面移动到前面, then 将::
替换为op
,将[]
替换为base
。因此,例如:变为
随着
+
和0
、fold_left
和fold_right
产生相同的结果。但在其他情况下,情况并非如此:例如,如果您使用-
而不是+
,结果会有所不同: 1 - (2 - (3 - (4 - ( 5 - 0)))) = 3,但 (((((0 - 1) - 2) - 3) - 4) - 5) = -15。I find it helpful to think of the fold operations as a generalization of what to do with a sequence of operations
fold_right (+) 0
applies the+
operation right-associatively, using0
as a base case:fold_left 0 (+)
applies it left-associatively:Now consider what happens if you replace
+
with::
and0
with[]
in both right- and left-folds.It may also be useful to think about the way
fold_left
andfold_right
work as "replacing" the::
and[]
operators in a list. For instance, the list[1,2,3,4,5]
is really just shorthand for1::(2::(3::(4::(5::[]))))
. It may be useful to think offold_right op base
as letting you "replace"::
withop
and[]
withbase
: for instancebecomes
::
became+
,[]
became0
. From this perspective, it's easy to see thatfold_right (::) []
just gives you back your original list.fold_left base op
does something a bit weirder: it rewrites all the parentheses around the list to go the other direction, moves[]
from the back of the list to the front, and then replaces::
withop
and[]
withbase
. So for instance:becomes
With
+
and0
,fold_left
andfold_right
produce the same result. But in other cases, that's not so: for instance if instead of+
you used-
the results would be different: 1 - (2 - (3 - (4 - (5 - 0)))) = 3, but (((((0 - 1) - 2) - 3) - 4) - 5) = -15.测试:
test: