Sto lavorando a un compilatore per un linguaggio concatenativo e vorrei aggiungere il supporto per l'inferenza del tipo. Capisco Hindley-Milner, ma sto imparando la teoria dei tipi mentre vado, quindi non sono sicuro di come adattarlo. Il seguente sistema è sano e decisamente inferibile?
Un termine è un letterale, una composizione di termini, una citazione di un termine o una primitiva.
Tutti i termini indicano funzioni. Per due funzioni ed , , ovvero la giustapposizione indica la composizione inversa. I letterali indicano funzioni niladiche.
I termini diversi da composizione hanno regole di tipo base:
In particolare sono assenti le regole per l'applicazione, poiché mancano le lingue concatenative.
Un tipo è letterale, una variabile di tipo o una funzione da pile a pile, dove una pila è definita come una tupla annidata a destra. Tutte le funzioni sono implicitamente polimorfiche rispetto al "resto della pila".
Questa è la prima cosa che sembra sospetta, ma non so esattamente cosa ci sia di sbagliato.
Per aiutare la leggibilità e ridurre le parentesi, suppongo che negli schemi di tipo. Userò anche una lettera maiuscola per una variabile che indica uno stack, anziché un singolo valore.
Ci sono sei primitivi. I primi cinque sono piuttosto innocui. dup
prende il valore più alto e ne produce due copie. swap
cambia l'ordine dei primi due valori. pop
scarta il valore più alto. quote
accetta un valore e produce un preventivo (funzione) che lo restituisce. apply
applica una quotazione alla pila.
L'ultimo combinatore, compose
dovrebbe prendere due citazioni e restituire il tipo della loro concatenazione, ovvero . Nel linguaggio concatenativo tipicamente staticoCat, il tipo diè molto semplice.compose
Tuttavia, questo tipo è troppo restrittivo: richiede che la produzione della prima funzione corrisponda esattamente al consumo della seconda. In realtà, devi assumere tipi distinti, quindi unificarli. Ma come scriveresti quel tipo?
Se lasci che indichi una differenza di due tipi, allora penso che tu possa scrivere il tipo di correttamente.compose
Questo è ancora relativamente semplice: compose
prende una funzione e uno f 2 : D → E . Il suo risultato consuma B in cima al consumo di f 2 non prodotto da f 1 e produce D in cima alla produzione di f 1 non consumato da f 2 . Questo dà la regola per la composizione ordinaria.
Tuttavia, non so che questo ipotetico corrisponda effettivamente a qualcosa, e lo sto inseguendo in circoli da abbastanza tempo che penso di aver fatto una svolta sbagliata. Potrebbe essere una semplice differenza di tuple?
Is there something horribly broken about this that I’m not seeing, or am I on something like the right track? (I’ve probably quantified some of this stuff wrongly and would appreciate fixes in that area as well.)
compose
is too restrictive? I have the impression that this is fine like this. (e.g. the restriction could be handled by unification like for application in like in the λ-calculus)
twice
defined as dup compose apply
, which takes a quotation and applies it twice. [1 +] twice
is fine: you’re composing two functions of type . But [pop] twice
is not: if , the problem is that , so the expression is disallowed even though it ought to be valid and have type . The solution is of course to put the qualifier in the right place, but I’m mainly wondering how to actually write the type of compose
without some circular definition.