For every accumulator , pattern matching makes foldl s a undefined the bottom value. Now use structural induction on a finite list prefix ending in the bottom value. The induction step is foldl s a (x:ps) = foldl s (s a x) ps; the induction hypothesis applies to every accumulator, including s a x. Consequently every such finite approximation has result .
An infinite lazy list is the limit of its finite prefixes, each interpreted as a finite approximation of a lazy list. Definable Haskell operations are Scott continuous maps, so the result on the infinite lazy list is the supremum of the results on these approximations. Every result is , hence foldl s a xs = undefined on every infinite input spine, irrespective of whether s would inspect the accumulator.
For a concrete separation, choose s = (&&), a = True, and xs = False : repeat True. The left fold is , whereas the right fold returns False after observing the first element: False && r does not demand r. It is reaching the end of the input spine, rather than strictness of the combining operation, that prevents this left fold from returning.
For finite lists, use structural induction: establish P []; then, for arbitrary x and xs, assume P xs and prove P (x:xs). The induction hypothesis must quantify over any other parameters that need to change in the step.
For all Haskell list values, finite terminating spines are insufficient: also establish P undefined, and allow arbitrary, possibly undefined, heads in the cons step. This proves the equation for finite partial lists ending in the bottom value. An infinite lazy list is the limit of these finite approximations. Equations between pure definable computable functions are preserved by those limits, so the equation extends to infinite inputs. This last argument requires that admissibility property; an arbitrary logical property of lists need not have it. The distinction between [] and the bottom value is essential.[ref]
Prove the stronger equation, quantified over the accumulator:
For [], both sides are f a. For the bottom value, both sides are bottom because f is a strict function. For the cons step, the universal induction hypothesis allows the accumulator to become g a x:
f (foldl g a (x:xs))
 = f (foldl g (g a x) xs)
 = foldl h (f (g a x)) xs
 = foldl h (h (f a) x) xs
 = foldl h (f a) (x:xs).
Thus structural induction proves the claim for finite and finite partial spines; definable continuity extends it to infinite lazy lists. Pointwise equality is exactly the asserted equality of function compositions. This is the left-fold fusion law.
Use a type with distinct values a and n, and let s _ y = y. Suppose a direct right fold with the same result type represented this left fold. The empty list forces k = n. The singleton lists force c n n = n and c a n = a. But then
foldr c k [a,n] = c a (c n n) = c a n = a,
foldl s n [a,n] = n.
Since a /= n, this is a counterexample. A direct right fold cannot recover whether its tail result n came from the empty list or from the singleton [n]. The obstruction already occurs on finite total inputs, so it also rules out an implementation valid on all lazy lists.
Change the right fold's result type to an accumulator-transforming function type:
foldlAsFoldr :: (b -> a -> b) -> b -> [a] -> b
foldlAsFoldr s n xs = foldr c id xs n
  where
    c x k a = k (s a x)
Thus c x k = \a -> k (s a x) and k = id in the question's notation. Here c :: a -> (b -> b) -> (b -> b), and the fold's base value is the identity function, not the initial accumulator n.
The recursion invariant is foldr c id xs a = foldl s a xs for every a. For [], both sides equal a. For a cons:
foldr c id (x:xs) a
 = c x (foldr c id xs) a
 = foldr c id xs (s a x)
 = foldl s (s a x) xs
 = foldl s a (x:xs).
At an undefined spine, applying the undefined folded function also gives the bottom value. The finite-approximation argument then covers infinite lazy lists. This is a continuation representation of a left fold: the result retains the operation still to be performed, avoiding the information loss in part (d).
Repeated constant time insertion constructs the representation:
fromList :: [a] -> List a
fromList = foldr cons nil
The right fold preserves order because cons prepends its argument. On a finite length- list, there are calls of cons; completely constructing the result takes time and constructors. This claim concerns finite inputs, not productivity of conversion from an infinite lazy list.
Use the same step from part (a):
groupFold :: Eq a => [a] -> [[a]]
groupFold = foldr prependRun []
The right fold obeys groupFold [] = [] and groupFold (x:xs) = prependRun x (groupFold xs), exactly the recursive equations already proved. Both implementations give the bottom value for an entirely undefined input spine. Their equal behaviour on finite partial lists, together with definable continuity, establishes equality on infinite lazy lists as well. The helper's irrefutable binding is what lets the first run be produced without demanding that all subsequent runs already exist.
The list fold criterion is: there must be a value z and a definable combining function c such that
The last equality says that all information needed about the tail factors through f xs; the combining function receives no other access to xs. These conditions give f = foldr c z.
Necessity follows from the defining equations of foldr, including its case distinction on the input list. Sufficiency follows by structural induction for finite lists and finite partial-list approximations. For infinite or partial lazy lists, the usual continuous semantics of these definable functions extends equality from the approximations to their limit. The strictness condition matters: agreement only on finite total lists does not establish agreement at . This is the fold factorisation criterion.
tails is not a direct list fold. Every foldr c z is strict in its list argument, but tails undefined = undefined : undefined has a defined outer constructor. Applying null distinguishes this result from .
ptails is not a direct list fold either. On a type with distinct values u and v,
A fold step given the same new head x and these equal folded tails must return the same result. However,
Thus the tail information needed by the next step does not factor through ptails; this violates the fold factorisation criterion even on finite total lists.
ntails is a direct list fold:
ntailsFold :: [a] -> [[a]]
ntailsFold = foldr step []
  where
    step x yss = (x : original yss) : yss
    original [] = []
    original (ys:_) = ys
When the tail is nonempty, its first nonempty suffix of a list is the tail itself; otherwise it is recovered as []. Hence original (ntailsFold xs) = xs. The inner case distinction is delayed beneath constructors, so the definition also preserves the required behaviour on partial and infinite lazy lists. Building a suffix head does not first demand the whole folded tail.
inits is not a direct list fold: inits undefined = [] : undefined has a defined outer constructor, while foldr c z undefined is .
Both pinits and ninits are direct list folds:
pinitsFold :: [a] -> [[a]]
pinitsFold = foldr (\x yss -> [] : map (x:) yss) []

ninitsFold :: [a] -> [[a]]
ninitsFold = foldr (\x yss -> [x] : map (x:) yss) []
For pinits, the combining function is exactly the recursive step above. For ninits, expand inits xs = [] : ninits xs and use
Neither step needs to inspect yss before producing its first outer constructor. Thus the definitions satisfy the fold factorisation criterion on partial as well as total lazy lists.
For a finite nonempty collection of exact real multipliers greater than one, the multiplicative closure of one can be enumerated by a shared lazy list: emit one, then merge its elementwise multiples by all generators. Every value after one has a smaller predecessor obtained by removing one factor, proving productivity by increasing value. There are only finitely many exponent tuples below any fixed bound, because every generator is greater than one; thus locally finite sorted-stream merge eventually emits every generated value. Equal products are emitted once.
A multiplier below one contradicts increasing order starting at one. A multiplier equal to one adds no new values and should be removed from the recursive streams; an empty remaining generator collection has the finite closure consisting of one. These qualifications concern exact arithmetic: finite precision or overflow can violate the order and growth assumptions.