Эта проблема может быть решена, если вы позволяете кернфункция складки, чтобы захватить лексическую область, содержащую изменяемые переменные. Тогда вы можете сохранить тип аккумулятора Boolean, и все же иметь достаточное состояние для вычисления.
псевдокод:
(foldl (let ([s 0])
(lambda (accum item)
;; if (equal? item 1) and s is not already 2
;; increment s
;; return (equal? s 1)
)
#f list)
Вы не можете решить эту проблему с помощью функции, которая не отражает какой-либо среды; но зачем это ограничивать? Функция - это код плюс лексическая среда, по определению.
В приведенном выше аккумуляторе в основном используется манекен; мы даже не смотрим на это, потому что состояние s
представляет все, что нам нужно. Мы могли бы использовать Boolean s
, так что состояние представляет собой комбинацию параметра аккумулятора и информации в s
. Мы могли бы разделить состояние между булевым аккумулятором и булевым s
(так что они вместе образуют двухбитовый счетчик, представляющий необходимые три состояния).
Вот неформальная доказательство того, что она не может быть решена только с функцией булевой возвращающие без изменяемого среды:
Заметим, что результат должен быть Boolean: существует ровно один 1
, правда или ложь?Таким образом, функция, которую мы используем как ядро сложения, должна иметь булевский накопитель, так как аккумулятор - это то, что возвращается.
Аккумулятор складки инкапсулирует все состояние, на которое алгоритм функции ядра принимает решение. Если, например, функция использует лексическую область действия, которая содержит изменчивые переменные, которые будут обманывать.
Алгоритм требует не менее трех состояний в аккумуляторе. Аккумулятор должен быть в некоторых начальных S0, из которого он переходит к S1, когда 1
видно, из которого он переходит к S2 когда другой 1
виден. Затем этот аккумулятор следует интерпретировать за пределами складки как S0
и S2
, обозначающий false, и S1
true.
Хотя мы могли бы теоретически изменить тип аккумулятора между посещенными элементами, у нас нет информации для этого; нам неизвестно, какой элемент последний. Если бы мы знали, что мы смотрим на последний элемент, мы можем потерять наш трехгосударственный накопитель до логического значения и вернуть его.
Поэтому вторая часть ответа Сильвестера использует продолжения: то алгоритм, вместо перехода к S2 могут выйти из складки непосредственно и производить ложный; тогда аккумулятор может быть булевым. (Более простой нелокальный механизм выхода будет достаточным вместо полномасштабных продолжений, таких как возврат из лексического блока).