从左侧的 OCaml 列表中添加元素

Adding Elements in List from Left OCaml

我写了一个函数:

let rec addAll f l =
  match l with
  | [] -> 0
  | [x] -> x
  | hd::tl -> let combined = addAll f tl in
                f (hd) combined
;;

我按标题工作,它将添加列表的所有元素。但是,我想编写此程序,使其具有左结合性,因此我希望它不是将元素 [1;2;3] 组合为 1 - (2 - 3),而是:(1 - 2) - 3。

关于如何使这个前向递归而不是尾递归有什么提示吗?或者我怎样才能使这个功能按我的意图工作?我知道我可以反转列表,但我想尝试另一种方式。

您的代码正确折叠。大致来说是这样的:

let addAll f l = List.fold_right f l 0

您想将其更改为左折。粗略地说,你想要这个:

let addAll f l = List.fold_left f 0 l

或者,您想要的更准确一点:

let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t

这第二个函数似乎可以满足您的要求:

# addAll (-) [1;2;3];;
- : int = -4

如果你想从头开始写(不使用List.fold_left),最简单的方法是使用累加器:

let addAllScratch f l =
    let rec iadd f accum l =
        match l with
        | [] -> accum
        | a::l -> iadd f (f accum a) l
    in
    match l with
    | [] -> 0
    | h :: t -> iadd f h t

这确实符合您的要求:

# addAllScratch (-) [1;2;3];;
- : int = -4

(本质上,我只是在代码中插入了List.fold_left的标准定义。)

let rec addAll f l =
  match l with
  | []       -> 0
  | [x]      -> x
  | x::y::tl -> addAll f ((f x y)::tl) 
;;

测试

# addAll (fun a b -> Printf.printf "(%d %d)" a b; a+b) [1;2;3];;
(1 2)(3 3)- : int = 6