Канонический способ сделать рекурсию с использованием чисто лямбда-выражений - это использовать комбинатор с фиксированной точкой , который является функцией со свойством
fixpoint f x = f (fixpoint f) x
Если предположить, что такой комбинатор существуетмы можем написать рекурсивную функцию как
factorial = fixpoint (\ff n -> if n == 1 then 1 else n * ff(n-1))
Единственная проблема в том, что fixpoint
сам все еще рекурсивен.В чистом лямбда-исчислении есть способы создания комбинаторов с фиксированной точкой, которые состоят только из лямбд, например, классический «комбинатор Y»:
fixpoint f = (\x -> f (x x)) (\x -> f (x x))
Но у нас все еще есть проблемы, потому что это определение не очень хорошонабран в соответствии с Haskell - и можно доказать, что невозможно написать хорошо типизированный комбинатор с фиксированной точкой, используя только лямбда-выражения и приложения-функции.Это может быть сделано путем использования вспомогательного типа данных для обработки в некоторой рекурсии типа:
data Paradox a = Self (Paradox a -> a)
fixpoint f = let half (Self twin) = f (twin (Self twin))
in half (Self half)
(Обратите внимание, что если инъекции и проекции из одноэлементного типа данных удаляются, это в точности Y-комбинатор!)