CR9191
CR9191

Reputation: 51

How do I add all elements from a list in F# recursively?

I'm very new to F# so I have been trying to sum all the elements(double integers) line in a text file to print out year and the total number of elements.

(sample from text file):

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

However, here is my recursion function to sum all the elements. I get the big error in the main with the explanation in the codes below.

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.

Error 1 The type 'float list' does not support the operator '+'

Upvotes: 3

Views: 3698

Answers (1)

Curt Nichols
Curt Nichols

Reputation: 2767

If you're just trying to get the work done List.sum is easy and won't overflow the stack.

Gustavo has given a good start but if you're summing many, many values you may overflow the stack. You didn't mention how many values you might need to some but if it were enough to overflow the stack you would want to switch to a tail-recursive implementation (see tail call and F# 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

With this implementation I can successfully sum a list of a million values or more without overflowing the stack.

If you'd like to go further with your understanding you might check out the source code for List.fold as it is a more generalized way of applying a function (even (+)) over a list.

The implementation of List.sum makes use of Seq.sum which shows accumulating a value over a sequence that doesn't necessarily require an actual container like List, but's that's clearly outside the stated problem.

Upvotes: 4

Related Questions