OCaml: fold_left, fold_right 转换

Posted

技术标签:

【中文标题】OCaml: fold_left, fold_right 转换【英文标题】:OCaml: fold_left, fold_right conversion 【发布时间】:2014-06-18 21:21:57 【问题描述】:

在http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html, 我们有:

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.

val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b

List.fold_right f [a1; ...; an] b is f a1 (f a2 (... (f an b) ...))。不是尾递归的。

问题是如何使用 List.fold_right 函数实现“fold_left”函数。 这是我在网上找到的答案:

let rec my_fold_left f a l = List.fold_right (fun x g a -> g (f a x)) l (fun x -> x) a;;

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

第一次写:

let rec my_fold_left_old f a l = List.fold_right (fun x a -> f a x) l a;;

val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

类型检查是正确的,但是 my_fold_left_old 是错误的,因为它从最后一个元素扫描列表到第一个元素。

谁能解释一下上面的函数my_fold_left,List.fold_right只能有3个参数,而上面的my_fold_left有4个参数?

【问题讨论】:

【参考方案1】:

这是咖喱。从本质上讲,List.fold_right 的类型为 ('a -> 'b -> 'b) -> 'a list -> 'b,并且此定义将该操作与 'b函数类型 一起使用。

如果您将'c -> 'd 替换为'b,您可以看到如何为List.fold_right 生成“四个参数”,从而跳过多余的括号:

('a -> 'c -> 'd -> ('c -> 'd)) -> 'a list -> 'c -> 'd

所以List.fold_right 折叠列表以生成一个函数,该函数应用于一个参数以生成最终结果。为了更清楚,让我们用一个命名的临时文件重写它:

 let foldl f init list =
  let fold_result =
    List.fold_right
      (fun elt g acc -> g (f acc elt))
      list
      (fun x -> x) in
  fold_result init

【讨论】:

以上是关于OCaml: fold_left, fold_right 转换的主要内容,如果未能解决你的问题,请参考以下文章

Ocaml 中的 List.Fold_Left 类型系统?

Debian 11 上的 Libgtksourceview-2.0dev 和 Ocaml/Opam/Ocaml-Top

OCaml:函数参数的默认值?

emacs ocaml REPL:“搜索程序:没有这样的文件或目录,ocaml”

OCaml和OCaml评估模型中的功能应用列表

ocaml 安装