List unfold 2026-10-24
Generate a list from a state: a step returning Nothing terminates; Just (x,s') emits x and continues from s'. Thus unfoldr step s = case step s of Nothing -> []; Just (x,s') -> x : unfoldr step s'. A list unfold decomposes the evolving state, whereas a list fold consumes existing constructors. Productivity depends on each demanded constructor becoming available, not merely on using lazy evaluation.
The list unfold operation has the following type signature and definition:
unfoldr :: (s -> Maybe (a,s)) -> s -> [a]
unfoldr step s = case step s of
  Nothing     -> []
  Just (x,s') -> x : unfoldr step s'

groupUnfold :: Eq a => [a] -> [[a]]
groupUnfold = unfoldr next
  where
    next [] = Nothing
    next (x:xs) = Just (x:ys,zs)
      where (ys,zs) = span (== x) xs
The seed is the unprocessed suffix of a list. An empty seed terminates the unfold; otherwise next returns the first maximal run and precisely the seed for the next call. Substituting the definition of unfoldr recovers part (c)'s equations, proving correctness. The Just pair and first group constructor can be produced before span finishes, retaining the same lazy evaluation behaviour.