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 转换的主要内容,如果未能解决你的问题,请参考以下文章
Debian 11 上的 Libgtksourceview-2.0dev 和 Ocaml/Opam/Ocaml-Top