Вычисление суммарной суммы списка в Haskell
Напишите функцию, которая возвращает текущую сумму списка. например [1,2,3,5] - [1,3,6,11]. Я пишу эту функцию, ниже которой можно вернуть окончательную сумму всех значений из списка. Так как я могу отделить их по одному?
sumlist' xx=aux xx 0
where aux [] a=a
aux (x:xs) a=aux xs (a+x)
Ответы
Ответ 1
Вы можете настроить свою функцию для создания списка, просто добавив a+x
к результату на каждом шаге и используя пустой список в качестве базового варианта:
sumlist' xx = aux xx 0
where aux [] a = []
aux (x:xs) a = (a+x) : aux xs (a+x)
Однако более идиоматично Haskell выражать подобные вещи как складку или сканирование.
Ответ 2
Я думаю, вам нужна комбинация scanl1 и (+), поэтому что-то вроде
scanl1 (+) *your list here*
scanl1 применит данную функцию к списку и сообщит каждое промежуточное значение в возвращаемый список.
Как, чтобы записать это в псевдокоде,
scanl1 (+) [1,2,3]
выводит список вроде:
[1, 1 + 2, 1 + 2 + 3]
или, другими словами,
[1, 3, 6]
Learn You A Haskell содержит множество отличных примеров и описаний сканирований, складок и многих других лакомств Haskell.
Надеюсь, что это поможет.
Ответ 3
Хотя scanl1 явно является "каноническим" решением, все же поучительно видеть, как вы могли бы это сделать с помощью foldl:
sumList xs = tail.reverse $ foldl acc [0] xs where
acc (y:ys) x = (x+y):y:ys
Или pointfree:
sumList = tail.reverse.foldl acc [0] where
acc (y:ys) x = (x+y):y:ys
Вот уродливый подход грубой силы:
sumList xs = reverse $ acc $ reverse xs where
acc [] = []
acc (x:xs) = (x + sum xs) : acc xs
Существует милое (но не очень эффективное) решение с использованием inits
:
sumList xs = tail $ map sum $ inits xs
Снова pointfree:
sumList = tail.map sum.inits
Ответ 4
В связи с другим вопросом, который я нашел таким образом:
rsum xs = map (\(a,b)->a+b) (zip (0:(rsum xs)) xs)
Я думаю, что это даже довольно эффективно.