Qualcuno ha usato la defunzionalizzazione polimorfica di Pottier e Gauthier in un compilatore modulare?


15

La defunzionalizzazione è una trasformazione del programma che converte i programmi di ordine superiore in programmi del primo ordine. L'idea è che dato un programma, ci sono solo finitamente molte lambda-astrazioni, quindi è possibile sostituire ogni lambda con un id e ogni applicazione di funzione con una chiamata a una procedura di applicazione che si ramifica su quell'id. Questo è talvolta usato nei compilatori per linguaggi funzionali, ma la sua applicabilità è limitata dal fatto che la defunzionalizzazione è una trasformazione dell'intero programma (è necessario conoscere staticamente tutte le funzioni del programma), e quindi solo i compilatori dell'intero programma fanno uso di esso.

Tuttavia, Pottier e Gauthier hanno dato un algoritmo di defunzionalizzazione tipizzato polimorficamente usando una tipizzazione più sofisticata che coinvolge GADT. Ora, data la loro codifica, è possibile aggiungere un caso generale al loro tipo di dati lambda che non è un tag, ma che contiene una funzione di ordine superiore. Ciò significa che dovrebbe essere possibile utilizzare la loro codifica per defunzionalizzare su base modulo per modulo.

Qualcuno l'ha fatto e mi ha indicato un compilatore che usa questa idea? (I compilatori di giocattoli vanno bene, e in effetti preferiscono.)

Risposte:


6

Un approccio è descritto da

Georgios Fourtounis e Nikolaos S. Papaspyrou. 2013. Supportare la compilazione separata in un compilatore defunzionalizzante. ARDESIA 2013.

Come menziona @gasche:

Un approccio diverso al problema sarebbe quello di considerare che ciascun modulo può definire il proprio tipo di "funzioni defunzionalizzate" e il dispatcher / gestore.

Puoi "collegare" quei tipi e gestori con un linker specializzato. A differenza dell'utilizzo di tipi di dati aperti, si concatena l'elenco dei costruttori e le funzioni del caso. Ma il linker deve aggiungere casi per un'applicazione parziale: senza l'analisi dell'intero programma, non è possibile prevedere quali applicazioni parziali possono essere utilizzate per quale funzione, quindi aggiungere tutti i casi. Una funzione -ary può essere parzialmente applicata agli argomenti (con ) e produrre una funzione di arity , che può essere parzialmente applicata di nuovo.nio0<io<nn-io


4

Ora, data la loro codifica, è possibile aggiungere un caso generale al loro tipo di dati lambda che non è un tag, ma che contiene una funzione di ordine superiore. Ciò significa che dovrebbe essere possibile utilizzare la loro codifica per defunzionalizzare su base modulo per modulo.

Potresti approfondire un po 'di più su cosa intendi qui? Non capisco in che modo l'aggiunta di un caso base (sarebbe al tipo di dati, alla corrispondenza dei modelli della funzione di dispacciamento o ad entrambi?) Aiuta la modularità nel modo in cui è stata descritta; a proposito, perché intendi esattamente per "modulo per modulo"?

Posso immaginare un "caso base" usato, all'interno di un dato modulo / programma, per una defunzionalizzazione selettiva : avresti un costruttore aggiuntivo per il tuo tipo di funzione reificata che non è un tag, ma incorpora semplicemente tutte le 'a -> 'bfunzioni, in modo da comprimere una funzione in questo costruttore, invece di assegnargli un tag reificato, ne impedirebbe la defezionalizzazione.

Un approccio diverso al problema sarebbe quello di considerare che ciascun modulo può definire il proprio tipo di "funzioni defunzionalizzate" e il dispatcher / gestore. Le funzioni del modulo M1dovrebbero essere digitate M1.arrowe applicate usando M1.apply, ecc. Sebbene funzioni bene per gli usi di primo ordine delle funzioni, non vedo bene come si possa estendere a funzioni di ordine superiore (che non dovrebbero sapere da dove proviene il loro argomento funzionale): se si raggruppa una funzione con il suo dispatcher, si rientra nuovamente nel regno delle chiamate di funzione indirette.

Infine, c'è nel documento a cui hai fatto riferimento una breve menzione dell'approccio dell'intero programma rispetto a quello modulare, ma non vedo come si collega alla tua proposta. Ciò che descrivono è espresso in termini di "estensioni aperte" di entrambe le funzioni e i tipi di dati (funzioni e tipi che potrebbero essere definiti su più moduli indipendenti). Questo è principalmente un modo ML per descrivere il fatto che è possibile rinviare la combinazione di analisi / trasformazioni di moduli indipendenti al momento del collegamento, rilassando la necessità della trasformazione dell'intero programma.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.