【问题标题】:Folding a list in OCaml在 OCaml 中折叠列表
【发布时间】:2018-09-25 15:24:35
【问题描述】:

在 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。但是我正在使用折叠功能实现该功能,但我被卡住了。具体来说,我不知道列表应该返回什么。我知道理想情况下应该将条件应用于列表中的每个项目,但我不知道语法应该是什么样子。 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

【问题讨论】:

    标签: recursion ocaml fold


    【解决方案1】:
    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。您希望您的谓词函数首先评估要布尔的元素,然后使用累加器“和”它。

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

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

    fold_left,另一方面,从列表的前面开始,并立即将每个元素与累加器组合。这不会通过一些递归函数调用“吃掉”你的堆栈。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      相关资源
      最近更新 更多