Bueno, y
tiene que ser de tipo (a -> b) -> c
, por alguna a
, b
c
y no sabemos todavía; después de todo, toma una función, f
, y la aplica a un argumento, por lo que debe ser una función que tome una función.
Desde y f = f x
(de nuevo, por alguna x
), sabemos que el tipo de retorno de y
debe ser el tipo de retorno de f
sí. Por lo tanto, podemos refinar un poco el tipo de y
: debe ser (a -> b) -> b
para algunos a
y b
que aún no conocemos.
Para averiguar qué es a
, solo tenemos que mirar el tipo del valor pasado a f
. Es y f
, que es la expresión que estamos tratando de averiguar el tipo de ahora. Estamos diciendo que el tipo de y
es (a -> b) -> b
(para algunos a
, b
, etc.), por lo que podemos decir que esta aplicación de y f
debe ser del tipo b
.
Por lo tanto, el tipo de argumento para f
es b
. Vuelva a poner todo junto, y obtenemos (b -> b) -> b
, que es, por supuesto, lo mismo que (a -> a) -> a
.
Aquí es una visión más intuitiva, pero menos preciso de las cosas: estamos diciendo que y f = f (y f)
, que podemos ampliar el equivalente a y f = f (f (y f))
, y f = f (f (f (y f)))
, y así sucesivamente. Por lo tanto, sabemos que siempre podemos aplicar otro f
en todo el asunto, y dado que "todo" en cuestión es el resultado de aplicar f
a un argumento, f
tiene que tener el tipo a -> a
; y dado que acabamos de concluir que todo es el resultado de aplicar f
a un argumento, el tipo de retorno de y
debe ser el mismo de f
- volviendo a juntarse, una vez más, como (a -> a) -> a
.
Suponiendo que se trata de un código real, acaba de disparar a quien se le ocurrió esto. –
@MartinJames: ¿Eh? ¿Qué crees que está mal con el código?No es la mejor manera de definir la función, pero es la más simple. –
@MartinJames, esa función es una función bien estudiada llamada [Y Combinator] (http://en.wikipedia.org/wiki/Fixed-point_combinator). (Creo que es correcto - ¡No puedo verificar la Wikipedia en este momento!) De todos modos, tal vez te despidan por ser tan filisteo :-) –