Estou aprendendo o conceito de continuações . Achei que uma boa ideia seria traçar o código fatorial típico quando escrito com a forma de continuação. Quero saber se meu entendimento está correto.
Código:
fact :: Integer -> (Integer -> Integer) -> Integer
fact 0 k = k 1
fact n k = fact $ n-1 (\v -> k (n*v))
-- call: fact 5 id
-- answer: 120
Foi assim que eu rastreei o código (acho que ser capaz de rastreá-lo é fundamental para entender como as continuações funcionam):
fact 5 id -->
fact 4 (\v -> id (5*v)) -->
fact 3 (\v -> (\v -> id (5*v)) (4*v)) -->
fact 2 (\v -> (\v -> (\v -> id (5*v)) (4*v)) (3*v)) -->
fact 1 (\v -> (\v -> (\v -> (\v -> id (5*v)) (4*v)) (3*v))) (2*v)) -->
fact 0 (\v -> (\v -> (\v -> (\v -> (\v -> id (5*v)) (4*v)) (3*v))) (2*v)) (1*v)) -->
(\v -> (\v -> (\v -> (\v -> (\v -> id (5*v)) (4*v)) (3*v))) (2*v)) (1*v)) 1
É assim que deveria ser traçado ou estou com os fundamentos errados?
PS: Entendo que os v
s são um pouco confusos, mas estou supondo que o interior v
esteja sombreando o exterior v
?
Sim, você tem os fundamentos corretos. A única coisa ligeiramente incorreta é a função com a qual você começa. O inner
v
está de fato sombreando o outerv
, o que você pode descobrir ativando todos os avisos do GHC. Para tornar as coisas mais fáceis de seguir, você pode querer dar nomes exclusivos às variáveis. Aqui está como eu escreveria, com a função inicial corrigida: