foldl (+) 0 на длинном списке это самая маленькая утечка памяти, какую я знаю, и дело в ней скорее в композиции, чем в арифметике. На каждом шаге строится санк (acc + x), который никто не форсирует до самого конца, и аккумулятор превращается в цепочку длиной со список. foldl' из Data.List на каждом шаге приводит аккумулятор к слабой заголовочной нормальной форме, и цепочка не возникает.
Ловушка в том, что у обеих версий один и тот же тип. В foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b ничего не сказано о том, сколько памяти держит результат, пока его не потребовали. Заверните свёртку в симпатичный комбинатор, и решение о строгости уйдёт ещё на уровень глубже, туда, где читатель его уже не видит.
С включённой оптимизацией анализ строгости в GHC часто спасает и обычный foldl. Именно поэтому в GHCi это застаёт врасплох.
Хуже того, foldl' доходит только до WHNF. Накапливайте пару (sum, count), и вычислится лишь конструктор пары, а оба поля останутся ленивыми. Нужны строгие поля или bang-паттерны на компонентах.
Поэтому строгость для меня больше не деталь оптимизации. Для комбинатора, который сворачивает, ей место в имени или в документации, рядом с типом.