I do not claim to understand this at all, but if it helps someone ... then yippee.
Consider the definition of fix . fix f = let x = fx in x . The stunning part is that x is defined as fx . But think about it for a moment.
x = fx
Since x = fx, we can substitute the value x on the right side of this value, right? So therefore ...
x = f . f $ x -- or x = f (fx) x = f . f . f $ x -- or x = f (f (fx)) x = f . f . f . f . f . f . f . f . f . f . f $ x -- etc.
So, the trick is for f to generate some structure so that later f can match this structure and complete the recursion without worrying about the full “value” of its parameter (?)
Unless, of course, you want to do something like creating an infinite list, as shown by luqui.
TomMD factorial explanation is good. Fixed signature of type (a -> a) -> a . A typical signature for (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1) is (b -> b) -> b -> b , in other words, (b -> b) -> (b -> b) . So we can say that a = (b -> b) . So fix accepts our function, which is a -> a or indeed (b -> b) -> (b -> b) , and will return a result of type a , in other words, b -> b , in other words, another function !
Wait, I thought it was supposed to return a fixed point ... not a function. Well, it does, sort of (because functions are data). You can imagine that this gave us the final function to search for factorial. We gave him a function that cannot recursively (therefore, one of the parameters to it is the function used for recursion), and fix taught it recursively.
Remember, as I said, f must generate some structure so that later f matches the pattern and ends? Well, that is not entirely true, I think. TomMD has illustrated how we can extend x to apply a function and move on to the base case. For his function, he used if / then, and that is what causes the termination. After repeated replacements, the in part of the entire definition of fix eventually ceases to be defined in terms of x , and this is when it is computable and complete.