2017-02-05 11 views
1

Предположим, у меня есть следующая функцияСохранить переменную и использовать его на рекурсии

printVariance :: [Float] -> IO() 
printVariance [] = return() 
printVariance (x:xs) 
    | x >= avg (x:xs) = print (x - avg (x:xs)) >> printVariance xs 
    | otherwise  = printVariance xs 

который получает список, чеки, элементы которых больше, чем средний и печатает их value - avg.

Моя проблема в том, что значение avg изменяется каждый шаг. Как я могу определить его только один раз и использовать его значение для рекурсии?

+2

Возможно, вы захотите переписать это с помощью складок и карт вместо прямого рекурсирования. Это позволит вам привязать привязку 'where' или' let', где вы определяете свой 'avg' как нечто по строкам' (foldr (+) 0 xs)/length xs'. – Michail

ответ

6

Переместить рекурсию в вспомогательную функцию. Эта функция может принимать среднее значение в качестве параметра, или вы можете определить локально значение printVariance и определить другую локальную переменную, содержащую среднее значение, которое функция могла бы получить.

В коде:

printVariance :: [Float] -> IO() 
printVariance xs = loop xs 
    where 
    average = avg xs 
    loop [] = return() 
    loop (x:xs) 
     | x >= average = print (x - average) >> loop xs 
     | otherwise = loop xs 

PS: Было бы хороший дизайн, чтобы отделить IO от логики программы. Поэтому я рекомендую вам сделать вашу функцию просто для создания списка значений, которые вы хотите, вместо того, чтобы печатать их и переместить IO в отдельную функцию (или просто main).

PPS: Вы действительно не вычисляете дисперсию, поэтому я бы рекомендовал назвать функцию чем-то еще.

+1

А, мы писали ту же программу. Я удалю свой ответ ради краткости :) – AJFarmar

+0

Ты прибил его, я не знаю, как я не мог этого думать, спасибо! –