【问题标题】:OCaml: fold_left, fold_right conversionOCaml: fold_left, fold_right 转换
【发布时间】: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个参数?

【问题讨论】:

    标签: functional-programming ocaml


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-14
      • 2022-01-12
      • 1970-01-01
      • 2012-09-03
      • 2015-12-01
      • 2012-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多