Ответ 1
Термин переписывания не должен выглядеть как функциональное приложение, но такие языки, как Pure, подчеркивают этот стиль, потому что a) бета-сокращение просто определить как правило перезаписи и b) функциональное программирование - это хорошо понятая парадигма.
Контрпример может представлять собой парадокс доски или кортежа, для которого термин переписывание также хорошо подходит.
Одно практическое различие между бета-редукцией и полным переписыванием терминов заключается в том, что правила перезаписи могут работать только с определением выражения, а не только с его значением. Это включает сопоставление шаблонов в приводимых выражениях:
-- Functional style
map f nil = nil
map f (cons x xs) = cons (f x) (map f xs)
-- Compose f and g before mapping, to prevent traversing xs twice
result = map (compose f g) xs
-- Term-rewriting style: spot double-maps before they're reduced
map f (map g xs) = map (compose f g) xs
map f nil = nil
map f (cons x xs) = cons (f x) (map f xs)
-- All double maps are now automatically fused
result = map f (map g xs)
Обратите внимание, что мы можем сделать это с помощью макросов LISP (или шаблонов С++), поскольку они представляют собой систему перезаписи терминов, но этот стиль размывает LISP четкое различие между макросами и функциями.
CPP #define не является эквивалентным, поскольку он не является безопасным или гигиеническим (sytactically-valid программы могут стать недействительными после предварительной обработки).
Мы также можем определить специальные предложения для существующих функций по мере необходимости, например.
plus (times x y) (times x z) = times x (plus y z)
Еще одно практическое соображение заключается в том, что правила перезаписи должны быть confluent, если мы хотим детерминированных результатов, т.е. мы получаем тот же результат, независимо от того, в каком порядке мы применяем правила в. Никакой алгоритм не может проверить это для нас (он вообще неразрешимый), а пространство поиска слишком велико, чтобы отдельные тесты могли нам рассказать. Вместо этого мы должны убедить себя, что наша система конфликтована каким-то формальным или неформальным доказательством; одним из способов было бы следовать системам, которые уже известны как конфлюентные.
Например, известно, что бета-редукция сливается (через теорему Церковно-Россера), поэтому, если мы напишем все наши правила в стиле бета-версии -обращения, тогда мы можем быть уверены, что наши правила сливаются. Конечно, именно то, что делают языки функционального программирования!