Обратите внимание, что то, что вы написали, не является реализацией комбинатора Y
.«Y
комбинатор» является конкретным «комбинатором с фиксированной точкой» в λ-исчислении.«Фиксированная точка» термина g
- это просто точка x
, такая, что
g(x) = x
«Комбинатор с фиксированной точкой» F
- это термин, который можно использовать для "производить "точки исправления.То есть, так что
g(F(g)) = F(g)
Термин Y = λf.(λx.f (x x)) (λx.f (x x))
является одним из многих, которому подчиняется это уравнение, т.е. он таков, что g(Y(g)) = Y(g)
в том смысле, что один термин может быть сведен к другому.Это свойство означает, что такие термины, включая Y
, могут использоваться для «кодирования рекурсии» в исчислении.
Относительно ввода отметим, что комбинатор Y
не может быть введен в простой тип λ-исчисления.Даже в полиморфном исчислении системы F. Если вы попытаетесь набрать его, вы получите тип «бесконечной глубины».Чтобы набрать его, вам нужна рекурсия на уровне типа.Поэтому, если вы хотите расширить, например, просто набранное λ-исчисление, до небольшого функционального языка программирования, вы предоставляете Y
в качестве примитива.
Вы не работаете с λ-исчислением, и ваш язык уже поставляется с рекурсией.Итак, то, что вы написали, является прямым определением «комбинатора» с фиксированной точкой в Scala.Просто, потому что быть фиксированной точкой следует (почти) немедленно из определения.
Y(f)(x) = f(Y(f))(x)
верно для всех x
(и это чистая функция), поэтому
Y(f) = f(Y(f))
, которое является уравнением для фиксированных точек.Что касается логического вывода для типа Y
, рассмотрим уравнение Y(f)(x) = f(Y(f))(x)
и пусть
f : A => B
Y : C => D
, поскольку Y : C => D
принимает f : A => B
в качестве входного значения,
C = A => B
поскольку Y f : D
является входом f : A => B
, то
D = A
, и поскольку выход Y f : D
такой же, как у f(Y(f)) : B
, то
D = B
до сих пор мыесть,
Y : (A => A) => A
, поскольку Y(f)
применяется к x
, Y(f)
- функция, поэтому
A = A1 => B1
для некоторых типов A1
и B1
итаким образом,
Y : ((A1 => B1) => (A1 => B1)) => A1 => B1