使用fold_left/right反转OCaml中的列表

发布于 2024-12-03 19:32:39 字数 756 浏览 1 评论 0原文

更新 - 解决方案

感谢 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春花秋月 2024-12-10 19:32:39

我发现将折叠操作视为对一系列操作的概括是有帮助的

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_leftfold_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 做了一些有点奇怪的事情:它重写列表周围的所有括号以向另一个方向移动,将 [] 从列表的后面移动到前面, then:: 替换为 op,将 [] 替换为 base。因此,例如:

fold_left 0 (+) 1::(2::(3::(4::(5::[]))))

变为

(((((0 + 1) + 2) + 3) + 4) + 5)

随着 +0fold_leftfold_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

a + b + c + d + e

fold_right (+) 0 applies the + operation right-associatively, using 0 as a base case:

(a + (b + (c + (d + (e + 0)))))

fold_left 0 (+) applies it left-associatively:

(((((0 + a) + b) + c) + d) + e)

Now consider what happens if you replace + with :: and 0 with [] in both right- and left-folds.


It may also be useful to think about the way fold_left and fold_right work as "replacing" the :: and [] operators in a list. For instance, the list [1,2,3,4,5] is really just shorthand for 1::(2::(3::(4::(5::[])))). It may be useful to think of fold_right op base as letting you "replace" :: with op and [] with base: for instance

fold_right (+) 0 1::(2::(3::(4::(5::[]))))

becomes

1 + (2 + (3 + (4 + (5 + 0))))

:: became +, [] became 0. From this perspective, it's easy to see that fold_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 :: with op and [] with base. So for instance:

fold_left 0 (+) 1::(2::(3::(4::(5::[]))))

becomes

(((((0 + 1) + 2) + 3) + 4) + 5)

With + and 0, fold_left and fold_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.

我ぃ本無心為│何有愛 2024-12-10 19:32:39
let rev =
  List.fold_left ( fun lrev b ->
    b::lrev
  ) [];;

测试:

# rev [1;2;3;4];;
- : int list = [4; 3; 2; 1]
let rev =
  List.fold_left ( fun lrev b ->
    b::lrev
  ) [];;

test:

# rev [1;2;3;4];;
- : int list = [4; 3; 2; 1]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文