在OCaml中折叠列表

时间:2018-09-25 06:00:44

标签: recursion ocaml fold

在OCaml中,典型的折叠功能如下:

let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
  begin match l with
  | [] -> base
  | x :: xs -> combine x (fold combine base xs)
  end

对于熟悉OCaml的人(与我不同),它的作用应该非常简单。

我正在编写一个函数,当列表中的所有项目都满足条件时返回true:如果条件x对于某个列表l中的所有x都为true。但是,我正在使用fold函数实现该函数,并且遇到了麻烦。具体来说,我不知道列表应该返回什么。我知道理想情况下应将条件应用于列表中的每个项目,但我不知道语法应如何显示。 x && acc可以使用,但无法通过非常简单的测试(如下所示)

let test () : bool =
  not (for_all (fun x -> x > 0) [1; 2; -5; -33; 2])
;; run_test "for_all: multiple elements; returns false" test

这是我的初步尝试。任何帮助表示赞赏:

let  for_all (pred: 'a -> bool) (l: 'a list) : bool =
fold (fun(x:'a)(acc: bool)->  _?_&&_?_  )false l

1 个答案:

答案 0 :(得分:2)

let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
  match l with
  | [] -> base
  | x::xs -> combine x (fold combine base xs)

let for_all (pred: 'a -> bool) (lst: 'a list) =
  let combine x accum =
    (pred x) && accum
  in
  fold combine true lst

您的Combine函数不应执行x && base,因为列表中的元素通常不是bool。您希望您的谓词函数首先将元素评估为bool,然后使用累加器对其进行“和”处理。

begin中不需要endfold。您可以仅使用match <identifier> with进行模式匹配。

fold有两种广泛的类型:fold_leftfold_right。您正在使用fold_right,基本上,它会遍历整个列表,并开始从列表末尾开始“组合”。这不是tail-recursive

另一方面,

fold_left从列表的最前面开始,并立即将每个元素与累加器组合在一起。这不会通过大量的递归函数调用“吞噬”您的堆栈。