Why is the type of this function (a -> a) -> a?
Prelude> let y f = f (y f)
Prelude> :t y
y :: (t -> t) -> t
Shouldn't it be an infinite/recursive type? I was going to try and put into words what I think it's type should be, but I just can't do it for some reason.
y :: (t -> t) -> ?WTFIsGoingOnOnTheRHS?
I don't get how f (y f) resolves to a value. The following makes a little more sense to me:
Prelude> let y f x = f (y f) x
Prelude> :t y
y :: ((a -> b) -> a -> b) -> a -> b
But it's still ridiculously confusing. What's going on?
Well,
y
has to be of type(a -> b) -> c
, for somea
,b
andc
we don't know yet; after all, it takes a function,f
, and applies it to an argument, so it must be a function taking a function.Since
y f = f x
(again, for somex
), we know that the return type ofy
must be the return type off
itself. So, we can refine the type ofy
a bit: it must be(a -> b) -> b
for somea
andb
we don't know yet.To figure out what
a
is, we just have to look at the type of the value passed tof
. It'sy f
, which is the expression we're trying to figure out the type of right now. We're saying that the type ofy
is(a -> b) -> b
(for somea
,b
, etc.), so we can say that this application ofy f
must be of typeb
itself.So, the type of the argument to
f
isb
. Put it all back together, and we get(b -> b) -> b
— which is, of course, the same thing as(a -> a) -> a
.Here's a more intuitive, but less precise view of things: we're saying that
y f = f (y f)
, which we can expand to the equivalenty f = f (f (y f))
,y f = f (f (f (y f)))
, and so on. So, we know that we can always apply anotherf
around the whole thing, and since the "whole thing" in question is the result of applyingf
to an argument,f
has to have the typea -> a
; and since we just concluded that the whole thing is the result of applyingf
to an argument, the return type ofy
must be that off
itself — coming together, again, as(a -> a) -> a
.