A definição de um combinador Y em F # é
let rec y f x = f (y f) x
f espera ter como primeiro argumento alguma continuação para os subproblemas recursivos. Usando o yf como uma continuação, vemos que f será aplicado a chamadas sucessivas à medida que pudermos desenvolver
let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc...
O problema é que, a priori, esse esquema impede o uso de qualquer otimização de chamada de cauda: de fato, pode haver alguma operação pendente nos f's, nesse caso, não podemos simplesmente alterar o quadro de pilha local associado a f.
Tão :
- por um lado, o uso do combinador Y requer uma continuação explícita diferente da própria função.
- por outro lado, para aplicar o TCO, gostaríamos de não ter nenhuma operação pendente em f e apenas chamar f em si.
Você sabe de que maneira esses dois poderiam ser reconciliados? Como um Y com truque de acumulador ou um Y com truque de CPS? Ou um argumento provando que não há como isso ser feito?
f
. Podemos ver que y
poderia chamar f
com um thunk (y f)
, mas, como você diz, f
pode ter alguma operação pendente. Eu acho que seria interessante saber se existe um combinador separado que seja mais amigável ao tailcall. Gostaria de saber se esta pergunta seria melhor atenção no site CS Stackexchange?