What I mean is that, from definition:
fix f
is the least fixed point of the functionf
In other words:
the least defined
x
such thatf x = x
.
The least defined value of any nullary type is undefined
. There is some ambiguity here still as undefined
may mean either "will throw an error" (the better) or "will never terminate" (the worse). As both reasoning and trial show, fix (+1)
and fix pred :: Word
both never seem to approach termination (even though pred 0
is an error), so the worse one of "never terminate" likely always gets chosen between these two alternatives. (What can escape fix
is the boring const 1
, but on that later.)
This is not the useful way of applying fix
.
The useful way of applying fix
is something along the lines of:
fix (\f x -> if x > 7 then f (x - 1) else x)
-- That is, using fix
to magically produce a recursive function. (This never ceases to amaze me.) This may be regarded as choosing between 2 functions: \f x -> f (x - 1)
and \_ x -> x
, one of which does never evaluate its first bound variable. This is a dangerous toy, as we may still obtain a function that is non-terminating for half its domain as easily as by accidentally flipping >
to <
or -
to +
.
So, somehow, of these two functions:
f1 = \f x -> f (x - 1)
f2 = \_ x -> x
-- The latter is "least defined ". If we squint hard, we can actually recognise our boring fellow const
in it, just flip
'd.
Now, this is counter-intuitive. f2
is actually more fault tolerant, so, in a sense, it's defined for more input values than f1
. (In particular, this is what lets it escape the otherwise infinite loop of fix
). Specifically, f2
is defined for all the same pairs (f, x)
of input as f1
plus the (undefined, x)
. Along the same line, const 1
is the most fault tolerant of all unary functions.
So, how do I understand definedness now?
some justification for the question
There is this answer nearby that kind of offers a different intuition for fix
than the one proposed in this question. It also emphasizes that for a full understanding one must pass to an external tutorial on denotational semantics.
I would like to have an answer that either supports, or explains the wrongs of, the intuition proposed here, and also, if domain theory really is behind that cursive ordering put forward in the comments, includes at least some rules of thumb that allow, however limited, but practical application of domain theory. One particular part of the question that I'd like to see light shed upon is whether a fix
able function can always be decomposed on a constant function and a reduction function, and what would the definition of these classes of functions be.
My wish is for an actual, practical answer on building useful and safe fix
-encoded recursion, backed by solid mathematical reasoning.