Лямбда-исчисление
Содержание
Лямбда-исчисление
Лямбда-исчисление — формальная система, придуманная в 1930-х годах Алонзо Чёрчем. Лямбда-функция является, по сути, анонимной функцией. Эта концепция показала себя удобной и сейчас активно используется во многих языках программирования.
Более формально, лямбда-функцию (или, лямбда-терм) можно задать следующей грамматикой:
Определение: |
В первом случае функция является просто переменной.
Во втором происходит аппликация (применение) одной функции к другой.
Это аналогично вычислению функции-левого операнда на аргументе-правом операнде.
В третьем — абстракция по переменной. В данном случае происходит
создание функции одного аргумента с заданными именем аргумента и телом функции.
Рассмотрим, например, функцию
. Эта функция принимает аргумент и возвращает его неизменённым. Например, . Аналогично, .Ещё один пример функции:
Приоритет операций
- Применение левоассоциативно:
- Аппликация забирает себе всё, до чего дотянется:
- Скобки играют привычную роль группировки действий
Свободные и связанные переменные
Связанными переменными называются все переменные, по которым выше в дереве разбора были абстракции. Все остальные переменные называются свободными.
Например, в
, связана, а — свободна. А в в своём первом вхождении переменная свободна, а во втором — связана.Рассмотрим функции
и . В первой из них при взгляде на понятно, что она имеет отношение к переменной, по которой производилась абстракция. Если по одной и той же переменной абстракция производилась более одного раза, то переменная связана с самым поздним (самым нижним в дереве разбора) абстрагированием. Например, в , переменная связана с самой правой абстракцией по .-конверсия
Рассмотрим функции
и . Интуитивно понятно, что они являются одинаковыми.
Определение: |
можно заменить на , если не входит свободно в , где означает замену всех свободных вхождений в на . Функции, получающиеся одна из другой с помощью -конверсий, называются -эквивалентными и обозначаются .Функции и являются -эквивалентными, а и — нет.\subsection{$\beta$-редукция} $\beta$-редукция олицетворяет идею счёта значения функции. Выражение вида | -конверсия — переименование связанной переменной. Выражение
\rangle$. При этом, голова списка будет храниться как показатель степени при $p_{len}$.
\begin{code} empty = pair' `App` zero' `App` one' cons = Lam "h" $ Lam "t" $ pair' `App` (succ' `App` (fst `App` Var "t"))
`App` (mult' `App` (snd `App` Var "t") `App` (power' `App` (ithPrime `App` (fst `App` Var "t")) `App` Var "h" ))
head = Lam "list" $ getExponent `App` (snd `App` Var "list")
`App` (ithPrime `App` (pred' `App` (fst `App` Var "list")))
tail = Lam "list" $ pair' `App` (pred' `App` (fst `App` Var "list"))
`App` (eliminateMultiplier `App` (snd `App` Var "list") `App` (ithPrime `App` (pred' `App` (fst `App` Var "list" ))) )
eliminateMultiplier' = Lam "f" $ Lam "n" $ Lam "m" $ if `App` (isZero' `App` (mod' `App` Var "n" `App` Var "m"))
`App` (Var "f" `App` (div' `App` Var "n" `App` Var "m") `App` Var "m") `App` Var "n"
eliminateMultiplier = fix' `App` eliminateMultiplier'
getExponent' = Lam "f" $ Lam "n" $ Lam "m" $ if `App` (isZero' `App` (mod' `App` Var "n" `App` Var "m"))
`App` (succ' `App`(Var "f" `App` (div' `App` Var "n" `App` Var "m") `App` Var "m")) `App` zero'
getExponent = fix' `App` getExponent' \end{code}
На основе этого всего уже можно реализовать эмулятор машины тьюринга: с помощью пар, списков чисел можно хранить состояния. С помощью рекурсии можно обрабатывать переходы. Входная строка будет даваться, например, закодированной аналогично списку: пара из длины и числа, характеризующего список степенями простых. Я бы продолжил это писать, но уже на операции $head [1, 2]$ я не дождался окончания выполнения. Скорость лямбда-исчисления как вычислителя печальна.
\ignore{ \begin{code}
four' = norm $ succ' `App` three' five' = norm $ succ' `App` four'
list2 = norm $ cons `App` one' `App` empty list32 = cons `App` zero' `App` list2
normFiveFact = normIO 0 $ fact' `App` five'
-- fiftysix = mult twentyeight two -- fiftyfive = pred fiftysix -- six = pred seven
--main = do print $ fiftysix (+1) 0 main = do
-- f <- normIO 0 $ ithPrime `App` three' -- f <- normIO 0 $ getExponent `App` (norm $ plus' `App` four' `App` four') `App` two' f <- normIO 0 $ head `App` (tail `App` list32) print $ toInt f
\end{code} }
\end{document} [1]