A biblioteca StreamMemo para Coq ilustra como memorizar uma função f : nat -> A
sobre os números naturais. Em particular quando f (S n) = g (f n)
, imemo_make
compartilha o cálculo de chamadas recursivas.
Suponha que, em vez de números naturais, desejemos memorizar funções recursivas sobre árvores binárias:
Inductive binTree : Set :=
| Leaf : binTree
| Branch : binTree -> binTree -> binTree.
Suponha que tenhamos uma função f : binTree -> A
estruturalmente recursiva, significando que existe uma função g : A -> A -> A
como essa f (Branch x y) = g (f x) (f y)
. Como construímos uma tabela de memorando semelhante para f
no Coq, de modo que os cálculos recursivos sejam compartilhados?
Em Haskell, não é muito difícil criar uma tabela de notas (veja o MemoTrie, por exemplo) e amarrar o nó. Claramente, essas tabelas de notas são produtivas. Como podemos organizar as coisas para convencer uma linguagem tipicamente dependente a aceitar que esse nó é produtivo?
Embora eu tenha especificado o problema no Coq, eu ficaria feliz com uma resposta no Agda ou em qualquer outro idioma de tipo dependente.
go
valor é uma função de um parâmetro Size. Em geral, não há compartilhamento entre chamadas de função independentes com o mesmo valor. Provavelmente, isso pode ser corrigido adicionando uma instrução let na definição deh (Branch l r)
. Em segundo lugar, a definição estratificada deBT
significa que duas árvores, de outra forma idêntica, terão valores diferentes quando ocorrerem em níveis diferentes. Esses valores distintos não serão compartilhados no MemoTrie.