La definizione di un combinatore Y in F # è
let rec y f x = f (y f) x
f prevede di avere come primo argomento un seguito per i sottoproblemi ricorsivi. Usando yf come continuazione, vediamo che f verrà applicato alle chiamate successive mentre possiamo svilupparci
let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc...
Il problema è che, a priori, questo schema preclude l'uso di qualsiasi ottimizzazione di coda: in effetti, potrebbe esserci qualche operazione in sospeso nelle f, nel qual caso non possiamo semplicemente mutare il frame dello stack locale associato a f.
Così :
- da un lato, l'uso del combinatore Y richiede una continuazione esplicita diversa rispetto alla funzione stessa.
- sull'altro per applicare il TCO, vorremmo non avere alcuna operazione in sospeso in f e chiamare solo f stesso.
Conosci un modo per riconciliare quei due? Come una Y con trucco accumulatore o una Y con trucco CPS? O un argomento che dimostra che non è possibile farlo?
f
. Possiamo vedere che y
potrebbe richiamare f
con un thunk (y f)
, ma come dici tu f
potresti avere qualche operazione in sospeso. Penso che sarebbe interessante sapere se esiste un combinatore separato che è più amichevole per le code. Mi chiedo se questa domanda attirerebbe maggiormente l'attenzione sul sito CS Stackexchange?