Ну, y
должно быть типа (a -> b) -> c
, для некоторых a
, b
и c
мы еще не знаем; в конце концов, он принимает функцию f
и применяет ее к аргументу, поэтому она должна быть функцией, принимающей функцию.
Поскольку y f = f x
(опять же, для некоторых x
), мы знаем, что тип возвращаемого значения y
должен быть типом возврата самого f
. Таким образом, мы можем немного уточнить тип y
: для некоторых a
и b
, которые мы пока не знаем, это должно быть (a -> b) -> b
.
Чтобы выяснить, что такое a
, нам просто нужно взглянуть на тип значения, переданного f
. Это y f
, это выражение, которое мы сейчас пытаемся выяснить, какой именно. Мы говорим, что тип y
равен (a -> b) -> b
(для некоторых a
, b
и т. Д.), Поэтому мы можем сказать, что это приложение y f
должно быть самого типа b
.
Таким образом, тип аргумента f
равен b
. Сложите все это вместе, и мы получим (b -> b) -> b
- что, конечно, то же самое, что и (a -> a) -> a
.
Вот более интуитивный, но менее точный взгляд на вещи: мы говорим, что y f = f (y f)
, который мы можем расширить до эквивалентных y f = f (f (y f))
, y f = f (f (f (y f)))
и так далее. Итак, мы знаем, что мы всегда можем применить еще один f
вокруг всего этого, и поскольку рассматриваемая «целая вещь» является результатом применения f
к аргументу, f
должен иметь тип a -> a
; и так как мы только что пришли к выводу, что все это результат применения f
к аргументу, тип возвращаемого значения y
должен быть типом самого f
- снова собираются вместе как (a -> a) -> a
.