OCaml:fold_left,fold_right转换

时间:2014-05-02 08:33:11

标签: functional-programming ocaml

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) ...))。不是尾递归。

问题是如何实施" fold_left"使用List.fold_right函数的函数。 这就是我在互联网上找到的答案:

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 个答案:

答案 0 :(得分:3)

它在干嘛。从本质上讲,List.fold_right的类型为('a -> 'b -> 'b) -> 'a list -> 'b,此定义将{em>函数类型用于'b

你可以看到它如何产生"四个参数" List.fold_right如果您将'c -> 'd替换为'b,则跳过冗余的parens:

('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