2

我正在尝试解决这个问题

练习 8.3 编写一个函数,接受一个数字列表并返回累积和;也就是说,一个新列表,其中第 i 个元素是原始列表中前 i + 1 个元素的总和。例如,[1, 2, 3] 的累积和为 [1, 3, 6]。

我写了这段代码,据我所知是正确的。

let lastItem = function 
  | [] -> 0
  | l -> List.hd (List.rev l);;

let rec cumulativeSumActual accum input =
match input with
  | [] -> accum
  | hd::tl -> cumulativeSumActual (accum::[(lastItem accum) + hd]) tl;;

let cumulativeSum = cumulativeSumActual [];;

let output = cumulativeSum [1; 2; 3;];;

let printer item =
    print_int item
    print_string "\n";;

List.iter printer output

但我得到了错误

user1@ubuntu:~/Documents/Programs$ ocamlc -o CumulativeList CumulativeList.ml
File "CumulativeList.ml", line 8, characters 33-38:
Error: This expression has type 'a list
       but an expression was expected of type 'a

然后我将代码更改为

  | hd::tl -> cumulativeSumActual (accum@[(lastItem accum) + hd]) tl;;

它奏效了!

但是我不明白为什么 cons 运算符不起作用,为什么 new list append 操作起作用?

cons 运算符应该简单地向列表中添加一个新项目,然后将新列表作为递归调用的第一个参数返回?

这是怎么回事?

4

2 回答 2

1

你有这个表达:

lastItem accum

的参数类型lastItem'a list

结果,accum具有'a list.

运算符::需要左侧的元素和右侧的列表,但您将其应用于左侧的列表,因此出现错误。@操作员允许在任一侧列出一个列表,因此它工作正常。

于 2013-09-09T04:41:59.650 回答
1

首先,con是将一个元素推送到列表的头部。例如,12::[13,1,3]。你不能con (::)一个列表到一个列表。显然,在您的代码中accumis 'a list,而不是'a. 您的代码(accum::[(lastItem accum) + hd])正在尝试con两个列表,对吗?

其次,@append连接两个列表的,这就是为什么你的| hd::tl -> 累积和实际 (accum@[(lastItem accum) + hd]) tl;; 是正确的。

第三,我建议解决方案是

let c_sum l =
  let rec sum pre acc = function
    | [] -> acc
    | hd::tl -> let tmp_sum = pre+hd in sum tmp_sum (tmp_sum::acc) tl
  in sum 0 [] l

PS,当您尝试连接两个列表时必须小心,因为通常此操作将花费 O(n),因为它需要遍历一个列表。

于 2013-09-09T09:21:48.450 回答