2015-02-12 3 views
2

Я очень новичок в F #, поэтому я пытался суммировать все строки (двойные целые числа) в текстовом файле, чтобы распечатать год и общее количество элементов.Как добавить все элементы из списка в 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' не поддерживает оператор '+'

ответ

3

Если вы просто пытаетесь получить работу List.sum легко и не будет переполнение стека.

Gustavo дал хорошее начало, но если вы суммируете многие, многие значения вы можете переполнить стек. Вы не говоря уже о том, сколько значений может потребоваться для некоторых, но если бы это было достаточно, чтобы переполнение стека вы хотите переключиться на хвостовую рекурсию реализации (см tail call и 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 

С этой реализации Я могу успешно суммировать список из миллиона значений или более без переполнения стека.

Если вы хотите продолжить свое понимание, вы можете проверить исходный код для List.fold, поскольку это более обобщенный способ применения функции (даже (+)) по списку.

Реализация List.sum использует Seq.sum, который показывает, накапливая значение по последовательности, которая не обязательно требует фактического контейнера, как List, но это, что явно за пределами указанной проблемы.

+0

Это действительно работает! Скажем, я хочу распечатать среднее значение для каждого элемента, будет ли это работать? пусть сумма (значения: двойной список) = let rec сумма значений accum = совпадающие значения с | [] -> аккумулятор | head :: tail -> sum tail (accum + head)/12.0 значения суммы 0.0 – CR9191

+0

Ну, вы, вероятно, не захотите называть это 'sum'. :) Вы точно знаете, сколько элементов находится в списке с List.length, поэтому вам не нужно его жестко кодировать. Кроме того, если вы уроните деление из рекурсивной части, вы разделите 1 раз, а не N; в этом случае вы можете просто повторно использовать свою функцию суммы в своей функции усреднения. Кроме того, позаботьтесь о проблемах с плавающей запятой вокруг маленьких или больших чисел (в зависимости от характера и количества значений, которые вы играете). –

Смежные вопросы