
--- it's notable that a turing machine is not a mathematical construct. things do not evaluate immediately. if an imperative system is told to evaluate a logical contradication, a situation arises where the output toggles on and off repeatedly, possibly. it depends on the system of evaluation. these various patterns could emerge depending on how f() or g() are coded. for example, one could imagine a (possible naive) f() that runs g() and observes g()'s behavior until it observes all possible covered code paths, then enumerates patterns in the behavior and determines whether completion will happen or not. since g() behaves in a counterposed way, the resulting pattern includes both f() and g() and specifically states the result is indeterminate. f()'s challenge is to consider the larger system, given this information, and possibly given these various flipflop behaviors, and output a single right answer. - if f() can specify the result is undecided, it can possibly succeed this way - if f() can hack g()'s behavior it can possibly succeed this way it's notable that although, with non-mathematical tricks, f() can hack the situation so as to output the right answer, it is then possibly outputting the wrong answer when evaluated within g(). is it still correct if it is doing this? what if g() is relying on f()'s output in some way? notably, f() has g() and could detect that. it seems interesting to consider how g() might treat this output and how f() might analyse that. allowing f() to output a pattern, and allowing g() to interpret that pattern, sounds a little interesting. for example if f() produces output that overtly states it depends on whether the evaluator is g(), then g() can either honestly respect that -- i think f() can succeed under those conditions -- or g() can ignore the request and instead consider how to behave if it is being evaluated by f() -- i think f() could be similarly stuck under that second situation. --- given there is some undecideability here, it might be possible to craft a convoluted f() that makes it so that the only thing that is undecideable is f()'s behavior when evaluated by g(). so, rather than hacking g() by not halting if run inside f(), instead f() would output that the answer is undecided, when run inside f(), maybe. then g() has no information to act on and can be predicted. it's notable that there are other rules f() does not have to play by, as well; for example, if it is simulating something, it could modify it during simulation or not simulate it accurately. if it is in a larger turing machine, it could modify other parts of the system state against the rules of functional programming. these things could be true of g() as well. - generally, useful approaches might come down to what the intended usecases of f() are. - if we consider making one f() that can resolve whether or not any g() halts, and we simply consider that f() must not halt, but can run forever, i think the cryptographic solution might work. the user must be able to provide unlimited cryptographic confirmation that they are not evaluating f() for the purposes of influencing another evaluation of f(). i feel like, if that works, there are other approaches too.