"Любая функция в конечных списках, которая определяется путем спаривания желаемого результата с списком аргументов, всегда может быть переопределена в терминах fold"

Я читал статью учебник по универсальности и выразительность fold, и я застрял в разделе о создании кортежей. После показа того, как нормальное определение dropWhile не может быть определено в терминах складки, был доказан пример, определяющий dropWhile с использованием кортежей:

dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile p = fst . (dropWhilePair p)

dropWhilePair :: (a -> Bool) -> [a] -> ([a], [a])
dropWhilePair p = foldr f v
  where
    f x (ys,xs) = (if p x then ys else x : xs, x : xs)
    v           = ([], [])

В документе говорится:

Фактически, этот результат является экземпляром (Meertens, 1992), в которой утверждается, что любая функция на конечных списках, определяемые путем объединения желаемого результата с списком аргументов, всегда можно переопределить в терминах складки, хотя и не всегда таким образом, чтобы не использовать оригинал (возможно, рекурсивного) определения для функции.

Я смотрел Meerten Paper, но не имел фона (теория теории категорий?) и не совсем понял, как это было доказано.

Существует ли относительно простое "доказательство", почему это так? Или просто простое объяснение того, почему мы можем переопределить все функции в конечных списках в терминах складки, если мы сопоставим результаты с исходным списком.

Ответ 1

Учитывая замечание, что вы можете/возможно, потребуется использовать оригинальную функцию внутри, требование, указанное в вашем вопросе, кажется мне тривиальным:

rewriteAsFold :: ([a] -> (b, [a])) -> [a] -> (b, [a])
rewriteAsFold g = foldr f v where
    f x ~(ys,xs) = (fst (g (x:xs)), x:xs)
    v            = (fst (g []), [])

EDIT: добавлен ~, после чего он работает и для бесконечных списков.