Sto avendo difficoltà a capire la definizione letrec per HM sistema che viene data su Wikipedia, qui: https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Recursive_definitionsForma corretta di letrec nel sistema di tipo Hindley-Milner?
Per me, la regola si traduce approssimativamente il seguente algoritmo:
- tipi inferire su tutto a la parte
letrec
definizione- assegnare variabili di tipo temporanee per ogni identificatore definito
- processare ricorsivamente tutte le definizioni delle tipologie temporanee
- a coppie, unificare i risultati con le variabili temporanee originali
- stretta (con
forall
) i tipi suggeriti, aggiungerli alla base (contesto) e dedurre tipi della parte espressione con esso
ho problemi con un programma come questo:
letrec
p = (+) --has type Uint -> Uint -> Uint
x = (letrec
test = p 5 5
in test)
in x
Il comportamento che sto osservando è la seguente:
- definizione di
p
ottiene tipo temporaneoa
- definizione di
x
ottiene un certo tipo temporaneo troppo, ma che è fuori del nostro ambito adesso - in
x
, definizione ditest
ottiene un tipo temporaneot
p
ottiene il tipo temporaneoa
dall'ambito, utilizzando la regola HM per una variabile(f 5)
viene elaborato dalla regola HM per l'applicazione, il tipo risultante èb
(e l'unificazione (a
unifica conUint -> b
)((p 5) 5)
viene processato dalla stessa norma, con conseguente più unificazione e digitarec
,a
ora in seguito unifica conUint -> Uint -> c
- ora, prova viene chiuso per digitare
forall c.c
- prova variabile
in test
ottiene l'istanza tipo (oforall c.c
) con variabili freschi, accrodingly alla regola HM per variabile, con conseguentetest :: d
(che è unificato contest::t
proprio sulla) - risultante
x
ha effettivamente digitared
(ot
, a seconda dell'umore di unificazione)
Il problema: x
dovrebbe ovviamente avere tipo Uint
, ma non vedo nessun modo quei due potevano mai unificare per produrre il tipo. C'è una perdita di informazioni quando il tipo di test
viene chiuso e ripetuto di nuovo che non sono sicuro di come superare o connettersi con sostituzioni/unificazioni.
Qualche idea su come correggere l'algoritmo per produrre x::Uint
digitando correttamente?O è una proprietà del sistema HM e semplicemente non scriverà un caso del genere (di cui dubito)?
Si noti che questo sarebbe perfettamente OK con lo standard let
, ma non volevo offuscare l'esempio con definizioni ricorsive che non possono essere gestite da let
.
Grazie in anticipo