List 从左OCaml向列表中添加元素

List 从左OCaml向列表中添加元素,list,ocaml,List,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 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
# addAllScratch (-) [1;2;3];;
- : int = -4
第二个函数似乎确实满足了您的要求:

let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t
# addAll (-) [1;2;3];;
- : int = -4
# addAllScratch (-) [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
这会满足您的要求:

let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t
# addAll (-) [1;2;3];;
- : int = -4
# addAllScratch (-) [1;2;3];;
- : int = -4

(本质上,我只是在代码中插入了
列表的标准定义。向左折叠)。粗略地说,是这样的:

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
# addAllScratch (-) [1;2;3];;
- : int = -4
第二个函数似乎确实满足了您的要求:

let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t
# addAll (-) [1;2;3];;
- : int = -4
# addAllScratch (-) [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
这会满足您的要求:

let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t
# addAll (-) [1;2;3];;
- : int = -4
# addAllScratch (-) [1;2;3];;
- : int = -4
(本质上,我只是在代码中插入了
List.fold_left
的标准定义。)

试验

试验


谢谢,很好的解释。我确实更喜欢V.Michel的回答,因为没有累加器。不过你的解释更透彻了。有一个累加器,输入的第一个元素被重复使用。但是,V Michel的代码当然更优雅。谢谢你,很好的解释。我确实更喜欢V.Michel的回答,因为没有累加器。不过你的解释更透彻了。有一个累加器,输入的第一个元素被重用。不过,V Michel的代码肯定更优雅。