Создание списка путем кумулятивного добавления элементов другого списка: Haskell

#haskell

#haskell

Вопрос:

Кажется, я не могу найти какую-либо информацию о функции высокого порядка, которая могла бы это сделать. Я нашел ссылку на cadd в нескольких местах, но не смог найти никакой информации в haskell api.

Я просто хочу взять список с плавающей точкой и создать из него другой список, кумулятивно добавив каждый. Исходный список всегда будет начинаться с нуля. Итак, если бы у меня был список [0,2,5,9], я бы получил список [0,2,7,16].

 accumulateTime :: [Float] -> [Float]
accumulateTime (x:xs) = cadd????
  

у меня есть другие части этого кода, которые что-то делают, но я не могу понять, как составить этот список.

Ответ №1:

Звучит так, как будто вам нужен вариант scanl , который связан с foldl , но создает список промежуточных результатов. Таким образом, foldl ( ) 0 суммируя список, scanl ( ) 0 создается список частичных сумм. Здесь вы, вероятно, захотите scanl1 ( ) , который не добавляет дополнительный ноль в начале.

 Prelude> scanl1 ( ) [0, 2, 5, 9]
[0,2,7,16]
  

Ответ №2:

Я думаю, что возможность перевести императивную версию этого кода в функциональный стиль — это хороший трюк в долгосрочной перспективе. Вот как я бы решил эту проблему на одном из этих варварских императивных языков:

 var acc = 0;
for each x in xs:
    acc = x   acc
    yield acc
  

Обратите внимание, что здесь у нас есть две переменные — список чисел и скользящая сумма. Когда мы преобразуем этот фрагмент кода в функциональный стиль, обычно приходится превращать циклы в (хвостовую) рекурсию, а переменные — в аргументы функции (поскольку это единственное место, где они могут «мутировать»).

 accum_helper acc list
  

Теперь мы можем попытаться разработать базовый вариант…

 accum_helper acc [] = ...
  

…рекурсивный случай

 accum_helper acc (x:xs) = ...
  

…и , наконец, используйте родительскую функцию для инициализации переменной

 accumulate xs = accum_helper 0 xs
  

Ответ №3:

Обратите внимание, что fold функции могут использовать переменную-накопитель любого типа — даже кортеж, где один элемент представляет собой совокупную сумму, а второй элемент — список предыдущих кумулятивных сумм.

Ответ №4:

Способ менее крутой, чем ответ хаммара, но другое решение:

 accumulate list = [sum $ take n list | n <- [1 .. length list]]
  

Комментарии:

1. Это не работает для бесконечных списков, в то время как решение Хаммара работает.