如何递归地添加F#中列表中的所有元素?

时间:2015-02-12 19:30:29

标签: list recursion f# element tail-recursion

我对F#很新,所以我一直在尝试将文本文件中的所有元素(双整数)行相加,以打印出年份和元素总数。

(来自文本文件的样本):

2010    **(the elements)->** 1.07   1.56    1.74    3.84    6.8 7.89    9.2 3.46    1.67    2.22    2.49    2.81

但是,这是我的递归函数,用于求和所有元素。我在下面的代码中解释了主要的错误。

let rec sum values:double list =
    if values = [] then
        []
    else
        values.Head + sum values.Tail

let main argv =
    // read entire file as list of strings:
    let file = ReadFile "rainfall-midway.txt"

    let (year, values) = ParseLine file.Head
    printfn "%A: %A" year (sum [values]) // values gets the error which i cannot understand at all.
  

错误1类型'float list'不支持运算符'+'

1 个答案:

答案 0 :(得分:4)

如果您只是想完成工作List.sum很容易,并且不会溢出堆栈。

古斯塔沃已经给了一个良好的开端但是如果你总结很多很多值,你可能会溢出堆栈。你没有提到你可能需要多少值,但如果它足以溢出堆栈,你会想要切换到尾递归实现(参见tail callF# Tail Recursive Function Example):

let sum (values: double list) =

    let rec sum values accum =

        match values with
        | [] -> accum
        | head :: tail -> sum tail (accum + head)

    sum values 0.0

通过这种实现,我可以成功地对一百万个或更多值的列表求和,而不会溢出堆栈。

如果您想进一步理解,可以查看List.fold的源代码,因为这是在列表中应用函数(甚至是(+))的更通用的方法。

List.sum的实现使用了Seq.sum,它显示了对序列的累积值,该序列不一定需要像List这样的实际容器,但这明显超出了所述问题