Per iniziare, una variabile di tipo "rigida" in un contesto indica una variabile di tipo associata a un quantificatore all'esterno di tale contesto, che pertanto non può essere unificata con altre variabili di tipo.
Questo funziona molto come le variabili vincolate da un lambda: dato un lambda (\x -> ...)
, dal "fuori" puoi applicarlo a qualsiasi valore tu voglia, naturalmente; ma all'interno, non puoi semplicemente decidere che il valore di x
dovrebbe essere un valore particolare. Scegliere un valore per x
all'interno della lambda dovrebbe sembrare piuttosto sciocco, ma questo è ciò che gli errori "non possono corrispondere a blah blah, tipo rigido variabile, blah blah" significa.
Si noti che, anche senza utilizzare i quantificatori espliciti forall
, qualsiasi firma di tipo di livello superiore ha un valore implicito forall
per ogni variabile di tipo menzionata.
Ovviamente, questo non è l'errore che si sta ottenendo. Ciò che una "variabile di tipo escape" significa è ancora più sciocco - è come avere un lambda (\x -> ...)
e provare a utilizzare valori specifici di x
all'esterno di lambda, indipendentemente dall'applicarlo a un argomento. No, non applicando il lambda a qualcosa e usando il valore del risultato - intendo in realtà usando la variabile stessa al di fuori dell'ambito in cui è definita.
Il motivo per cui questo può accadere con i tipi (senza sembrare ovviamente assurdo come l'esempio con un lambda) è perché ci sono due concetti di "variabili di tipo" che fluttuano: durante l'unificazione, si hanno "variabili" che rappresentano tipi indeterminati, che vengono poi identificati con altre di tali variabili tramite l'inferenza del tipo. D'altra parte, si hanno le variabili di tipo quantificato sopra descritte che sono specificatamente identificate come diverse dai possibili tipi.
Considerare il tipo di espressione lambda (\x -> x)
. Partendo da un tipo completamente indeterminato a
, vediamo che accetta un argomento e lo stringiamo a a -> b
, quindi vediamo che deve restituire qualcosa dello stesso tipo del suo argomento, quindi lo restringiamo ulteriormente a a -> a
. Ma ora funziona per qualsiasi tipo di a
che potresti volere, quindi gli diamo un quantificatore (forall a. a -> a)
.
Quindi, una variabile di tipo escape si verifica quando si ha un tipo associato da un quantificatore che i dati di GHC devono essere unificati con un tipo indeterminato all'esterno dello l'ambito di tale quantificatore.
Quindi a quanto pare ho dimenticato di spiegare in realtà il termine "variabile tipo skolem" qui, heh. Come accennato nei commenti, nel nostro caso è essenzialmente sinonimo di "variabile di tipo rigido", quindi quanto sopra spiega ancora l'idea.
Non sono del tutto sicuro da dove ha avuto origine il termine da, ma direi che coinvolge Skolem normal form e rappresentando esistenziale quantificazione in termini di universale, come si fa in GHC. Una variabile di tipo skolem (o rigida) è quella che, all'interno di un certo ambito, ha un tipo sconosciuto ma specifico per qualche ragione - essendo parte di un tipo polimorfico, proveniente da un tipo di dati esistenziali, & c.
http://hackage.haskell.org/trac/ghc/ticket/7194? –
Sì, l'ho visto, ma quel biglietto non dà molte spiegazioni su cosa sia uno skolem. –
Sto cercando una spiegazione di cosa sono gli skolem e cosa li causa, invece di specificare specificamente come correggere il mio codice. Ho già corretto il mio codice, ma non sono proprio sicuro del motivo per cui ciò che ho fatto ha fatto sparire gli skolem ... –