AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 23–29 September 2026

Choose a Haskell list fold by demand on its result

Haskell list folds need different choices for strict accumulation and incremental output. Read result demand before applying rules about direction and memory.

Citiți articolul în română

Looking back from November 2026 at the week of 23 September, the useful question about a Haskell list fold is what the consumer demands from the result. Strict accumulation and incremental production require different evaluation behavior. Choosing by the apparent direction in a function name hides that distinction. A maintenance review should connect the combining function, the list structure and the consumer before making a claim about space use or deciding that one fold is always the right replacement.

The Haskell blog post dated 25 September republishes Alexis King's explanation from a Hasura review discussion on 26 September 2019. These are two locations for the same explanation, rather than independent performance evidence or a new language feature. The original review concerned a strict map-deletion accumulator. The republication makes the reasoning easier to find; it does not turn that particular review into a measurement of every program that folds a list.

Start with the result being requested

A total over a finite list and a producer whose consumer requests only a prefix are different jobs. The total needs the contribution of every input before its final answer is available. The prefix consumer may be able to stop earlier if the producing computation permits it. A useful review starts by naming which job the code actually performs. Similar-looking fold expressions can have different space and evaluation behavior because their callers demand different amounts of the result.

In King's explanation, left and right describe association rather than opposite traversals of an ordinary list. With lazy accumulation, a left-associated calculation can retain a chain of deferred work instead of updating a finished accumulator at each step. For a strict accumulating operation on lists, foldl' addresses that deferred accumulation. The important part of the recommendation is the strict operation and the demand for the accumulated result. The apostrophe should not become a substitute for understanding those premises.

The practical distinction is between representing work to be done and doing enough of it while progressing. A long chain of deferred additions can occupy space even though the eventual answer is small. Removing that chain can make the evaluation better match the intended running total. This explains a possible space problem without establishing a measured memory reduction in an application. The actual accumulator and the surrounding program still determine what remains live during execution.

Incremental production needs useful laziness

A right-associated fold can expose part of a result before demanding its recursive remainder when the combining function is lazy in that remainder. A consumer that takes only a prefix can then avoid demanding the rest. That condition is necessary to the argument. foldr is not automatically a streaming solution for every combining function, and a consumer that demands the complete result can remove the hoped-for opportunity to save work. Both ends of the computation matter.

This is why replacing every fold with a strict accumulator can damage the intended evaluation pattern. A program constructing output incrementally has a different contract from one consuming the whole input into a final summary. For the former, delaying the remainder can be useful. For the latter, delaying a strict accumulated calculation can retain unnecessary work. Laziness is neither an unconditional defect nor an unconditional advantage. Its value depends on which demand it postpones and whether that work is eventually needed.

For a business application, this distinction can matter when input sizes grow beyond the cases that originally shaped the implementation. Code that seemed harmless on a small list may retain more work than intended on a much larger one. Conversely, making an incremental producer eager can move latency and resource use into work that its caller never requests. These are possible consequences to investigate, not reports of a customer incident or an experiment performed for this article.

Review the premises before changing the function

A useful review comment should identify the relevant operation and demand. Saying that a strict accumulator should be forced as it progresses gives the author something to verify. Saying merely that a named fold is bad encourages mechanical changes with poorly understood consequences. The original Hasura review is valuable because it connects the recommendation to a concrete strict operation. Its broader explanation supports reasoning about other list cases while retaining the conditions that make the recommendation apply.

The accumulator also deserves inspection beyond its name. Forcing a compound value sufficiently to expose its outer form does not automatically establish that every component has been fully evaluated. A claim of bounded space therefore needs an account of the state actually retained. This is a limit on applying the rule, rather than an instruction to make every component maximally strict. Excess strictness can change when work occurs. The implementation should match the result contract the application needs.

The strongest counterargument is proportion. King notes that the difference often does not matter much for small lists. A broad rewrite may cost more review effort than the small case warrants. Understanding the rule can improve new code and targeted maintenance without making every existing fold an urgent optimization project. Where a clearer library operation already expresses the intended result, retaining that clarity can also help a reviewer see the real demand instead of arguing about a low-level formulation.

Keep the list boundary intact

The explanation explicitly limits its rules to lists. Other structures organize their remainder differently, so conclusions about ordinary list association cannot be transferred unchanged to every Foldable. A tree and a differently constructed sequence need their own evaluation account. This boundary is part of the original argument, not a minor footnote. Dropping it would turn a useful teaching rule into a misleading universal policy.

For software maintenance, use result demand to justify a targeted change. State whether the function consumes the entire list into strict state or can produce useful output incrementally, then check the combining function and caller against that statement. Preserve the limits for small inputs and other structures. The best outcome of the 2026 republication is a better explanation in the next review, with the necessary premises still attached.