Alternativas à desfuncionalização


Respostas:


6

Existem três abordagens principais (que eu conheço) para implementar funções de ordem superior. Defuncionalização, conversão de fechamento / elevação lambda e combinadores.

Vamos write para o tipo de uma função de ordem superior de para e para o tipo de ponteiros de função de estilo C de para . (Se quiséssemos formalizar isso, poderíamos dizer que a abstração do ponteiro de função é permitida apenas no ambiente vazio.)UMABUMABUMABUMAB

Conversão de fechamento é a ideia de que escolhemos a representação O normalmente será a tupla que mantém os valores de variáveis ​​livres no site da lambda abstração. Poderia ser alguma outra representação embora.

UMABE.(E,(E,UMA)B)
E

O levantamento do Lambda adota uma abordagem um pouco diferente e mais global, em que uma abstração do lambda é puxada para fora, contendo escopos, adicionando variáveis ​​livres como parâmetros ao longo do caminho, até atingir o escopo de nível superior. Enquanto isso lida com a estrutura de blocos, para lidar com funções de ordem superior de funções, é necessário permitir uma aplicação parcial. Você pode então passar funções parcialmente aplicadas, mas essa é basicamente a mesma representação que a conversão de fechamento.

Se você deseja eliminar os ponteiros de função, podemos usar a defuncionalização, que, nesse caso especial, simplesmente produz uma enumeração. Porém, há poucas razões para fazer isso, pois os ponteiros de função são construções naturais na maioria das linguagens assembly.

A próxima abordagem é usar combinadores. Isso é basicamente o mesmo que o levantamento lambda e o uso de aplicativos parciais, exceto que um conjunto fixo de funções de nível superior é usado e todas as outras funções são expressas como combinações daquelas. (Se eles não tiverem um conjunto fixo predefinido de combinadores, isso geralmente é apenas uma abordagem baseada em levantamento lambda, como eu descrevi acima.) Uma função de ordem superior seria efetivamente representada por um valor em um tipo de dados usando a sintaxe Haskell como o seguinte (usando SKcombinadores ):

data CA = S | K | App CA CA -- plus other things in reality, like primitive values

Uma representação mais parecida com o cálculo da coluna vertebral provavelmente faz mais sentido para a eficiência. Ou você pode fazer algo como:

data CA = S0 | S1 CA | S2 CA CA | K0 | K1 CA  

A aplicação de uma função de ordem superior divide-se em dois casos: um combinador foi totalmente aplicado e, portanto, deve ser executado, ou retornamos um novo valor que representa o aplicativo (parcial).

Ainda não fiz uma pesquisa exaustiva, mas estou bastante confiante de que variações na conversão de fechamento são de longe a estratégia de implementação mais comum para funções de ordem superior (portanto, elas costumam ser chamadas de "fechamento"). Tem as boas propriedades de ser modular, simples e razoavelmente eficiente, mesmo na sua forma mais ingênua. É preciso uma boa escolha de combinadores de base e alguma inteligência para obter abordagens baseadas em combinador para um bom desempenho. A defuncionalização simplesmente não é amplamente usada, até onde eu sei, mas há poucas razões para não tirar proveito dos ponteiros de função. Na medida em que você faz, por exemplo, em vez de uma análise de caso grande, você tem uma tabela de indicadores de função que indexa, basicamente recriou a conversão de fechamento.

Existem outras abordagens. Uma é a instanciação de modelos, que consiste basicamente em levar redução literalmente, e simplesmente literalmente substituir termos por outros termos. Geralmente, isso requer ter e manipular uma estrutura abstrata em forma de árvore de sintaxe. Funções de ordem superior são então representadas por seus termos lambda (sintáticos) ou "modelos" dos mesmos, que podem simplificar a execução das substituições.β

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.