У всех трех решений есть утечки пространства, возможно, именно это и приводит к отсутствию ответа.
В Haskell, при сокращении большого списка до единого итогового значения, очень легко непреднамеренно вызвать утечку пространства, если мы никогда не "посмотрите на "промежуточные значения вычисления.Мы можем получить гигантское дерево неоцененных громов, скрывающееся за, казалось бы, безобидным единственным значением Double
.
Пример foldr
протекает, потому что foldr
никогда не вынуждает свой аккумулятор к слабымголова нормальной формы .Вместо этого используйте строгий левый foldl'
(вам нужно будет переупорядочить некоторые аргументы функции).foldl'
должен обеспечить, чтобы промежуточные значения Double
оставались "маленькими", а thunks не накапливались.
Пример явной рекурсии опасен, поскольку он не является хвост-рекурсивным и для больших списков можетвызвать переполнение стека (мы многократно помещаем значения в стек, ожидая завершения следующего рекурсивного вызова).Решение может заключаться в том, чтобы сделать функцию хвостовой рекурсивной, передав передачу промежуточного результата в качестве дополнительного параметра , и добавив шаблон взрыва для этого параметра, чтобы убедиться, что thunks не накапливается.
В примере product
утечка, потому что, к сожалению, ни функции sum
, ни product
не являются строгими.Для больших списков лучше использовать foldl'
.(Существует также ошибка, как это было упомянуто в комментариях.)