我正在努力解决这个问题
练习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运算符不起作用,为什么新列表会附加运算?
cons运算符应该只是在列表中添加一个新项目,然后将新列表作为递归调用的第一个参数返回?
发生了什么事?
答案 0 :(得分:1)
你有这个表达:
lastItem accum
lastItem
的参数类型为'a list
。
因此,accum
的类型为'a list
。
运算符::
左侧需要一个元素,右侧需要一个列表,但是您将其应用到左侧的列表中,因此出现错误。 @
运算符允许在任何一方使用列表,因此它运行正常。
答案 1 :(得分:1)
首先,con
是将元素推送到头部的列表。例如,12::[13,1,3]
。您不能con (::)
列表中的列表。在您的代码中,accum
显然是'a list
,而不是'a
。您的代码(accum :: [(lastItem accum)+ hd])正在尝试con
两个列表,对吗?
其次,@
是连接两个列表的append
,这就是为什么你的 | hd :: tl - > cumulativeSumActual(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
P.S。,当您尝试连接两个列表时必须小心,因为通常此操作将采用O(n),因为它需要遍历一个列表。