Definicja kombinatora Y w F # to
let rec y f x = f (y f) x
f oczekuje, że jako pierwszy argument będzie miała kontynuację rekurencyjnych podproblemów. Używając yf jako kontynuacji, widzimy, że f będzie stosowane do kolejnych wywołań w miarę rozwoju
let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc...
Problem polega na tym, że z góry ten schemat wyklucza stosowanie jakiejkolwiek optymalizacji wywołania ogona: w rzeczy samej, może być pewna operacja oczekująca na f, w którym to przypadku nie możemy po prostu mutować lokalnej ramki stosu powiązanej z f.
Więc :
- z jednej strony użycie kombinatora Y wymaga wyraźnej innej kontynuacji niż sama funkcja.
- w innych przypadkach, aby zastosować TCO, chcielibyśmy, aby żadna operacja nie oczekiwała na f, a jedynie wywołanie samej f.
Czy znasz jakiś sposób na pogodzenie tych dwóch rzeczy? Jak Y z akumulatorem, czy Y z sztuczką CPS? A może argument dowodzący, że nie da się tego zrobić?
f
. Widzimy, że to y
może zadzwonić f
z trzaskiem (y f)
, ale, jak mówisz, f
może mieć trochę oczekującej operacji. Myślę, że byłoby interesujące wiedzieć, czy istnieje oddzielny kombinator, który jest bardziej przyjazny dla ogona. Zastanawiam się, czy to pytanie zwróciłoby większą uwagę na stronie CS Stackexchange?