Let pack be the function [a] -> [[a]] which takes a list and groups consecutive repeated elements into sublists.
Here are two implementations of pack in Haskell.
pack :: (Eq a) => [a] -> [[a]]
pack x = reverse $ foldl f [] x where
f cks@(ck1:_):rest) x
| x == ck1 = (x:ck):rest
| otherwise [x]:cks
f _ x = [[x]]
pack' (x:xs) = let (first,rest) = span (==x) xs
in (x:first) : pack' rest
pack' [] = []
These implementations have a critical semantic difference: the first implementation fails to terminate if we apply it to an infinite list, e.g. [1..]. But the second implementation does work for infinite lists. For example, head $ pack' [1..] evaluates.
My guess is the let in notation is lazy, hence span (which uses let-in in its Prelude definition) only evaluates finitely many expressions when we apply pack' on an infinite list.
However, this is an unsatisfactory explanation to me, because I can replace reverse with the following definition.
reverse' = foldl (\y x0 -> x0:y) []
If we do this, every expression in pack folds from left to right—so I would expect this to work for infinite lists—yet it still hangs.
The question: Why does pack' work for infinite lists and not pack?