Hindley - Damas - Milner tyyppijärjestelmä
- Teetkö Haskellia harkkana?
- Tässä pohja modernille tyypinpäättelylle
Hindley - Damas - Milner systeemi
Abstrakti | Konkreetti | Selitys | |
---|---|---|---|
mono \(\tau\) ::= | \(\alpha\) | \(\alpha\) | (tyyppi)muuttuja (Int, Either, Bool, \(\beta\)) |
\(\text{fun}[\tau_1;\tau_2]\) | \(\tau_1\rightarrow\tau_2\) | Funktiotyyppi | |
\(\text{con}[C;\tau_1;\tau_2\dots\tau_n]\) | \(C\ \tau_1\ \tau_2\dots\tau_n\) | Konstruktori (List int, Either int bool) | |
poly \(\sigma\) ::= | \(\tau\) | \(\tau\) | monotyyppi |
\(\text{forall}[\alpha;\alpha.\sigma]\) | \(\forall\alpha . \sigma\) | kvanttori (\(\forall\alpha.\text{List}\ \alpha \rightarrow (\alpha \rightarrow \beta) \rightarrow \text{List}\ \beta\)) | |
exp \(e\) ::= | \(x\) | \(x\) | (tavallinen) muuttuja |
\(\text{ap}[e_1;e_2]\) | \(e_1\ e_2\) | funktiokutsu | |
\(\text{lam}[x;x.e]\) | \(\lambda x \rightarrow e\) | nimetön funktio | |
\(\text{let}[x;e_1,x.e_2]\) | \(\text{let}\ x = e_1\ \text{in}\ e_2\) | Muuttujan sidonta |
Ts. Lambdakalkyyli, johon on lisätty let
ja tyypit
- Monotyypit ovat samoja vain itsensä kanssa
- \(\forall\alpha.\alpha\rightarrow\alpha\) on sama kuin haskellin
a -> a
(taiforall a. a->a
)
Kysymys
Onko sallittua kirjoittaa: \(\forall\alpha. \alpha \rightarrow \forall\beta.\beta\)?
Abstrakti | Konkreetti | Selitys | |
---|---|---|---|
mono \(\tau\) ::= | \(\alpha\) | \(\alpha\) | (tyyppi)muuttuja (Int, Either, Bool, \(\beta\)) |
\(\text{fun}[\tau_1;\tau_2]\) | \(\tau_1\rightarrow\tau_2\) | Funktiotyyppi | |
\(\text{con}[C;\tau_1;\tau_2\dots\tau_n]\) | \(C\ \tau_1\ \tau_2\dots\tau_n\) | Konstruktori (List int, Either int bool) | |
poly \(\sigma\) ::= | \(\tau\) | \(\tau\) | monotyyppi |
\(\text{forall}[\alpha;\alpha.\sigma]\) | \(\forall\alpha . \sigma\) | kvanttori (\(\forall\alpha.\text{List}\ \alpha \rightarrow (\alpha \rightarrow \beta) \rightarrow \text{List}\ \beta\)) | |
exp \(e\) ::= | \(x\) | \(x\) | (tavallinen) muuttuja |
\(\text{ap}[e_1;e_2]\) | \(e_1\ e_2\) | funktiokutsu | |
\(\text{lam}[x;x.e]\) | \(\lambda x \rightarrow e\) | nimetön funktio | |
\(\text{let}[x;e_1,x.e_2]\) | \(\text{let}\ x = e_1\ \text{in}\ e_2\) | Muuttujan sidonta |
\(\Gamma\) - Konteksti
- Huom: Tässä vaiheessa tyypeillä ja lausekkeilla ei ole mitään yhteyttä!
- Raa'asti: Mitä tarkoittaisi tyyppi \(\text{int}\)?
- Tyyppejä voi tarkastella vain kontekstissaan. Merkitys syntyy siinä.
\(\Gamma\) - Konteksti
- "\(x\) on tyyppiä \(\tau\)" merkitään \(x : \tau\)
- \(\Gamma\) on joukko tälläisiä merkintöjä
- Ts. \(\Gamma\) merkitsee jo tiedettyjä tyypityksiä.
- "\(\Gamma,x:\tau\)" tarkoittaa "lisätään kontekstiin tieto, että \(x\) on tyyppiä \(\tau\)"
- "\(\Gamma\vdash x:\alpha\)" tarkoittaa, että annetusta ympäristöstä \(\Gamma\) voidaan päätellä, että \(x\) on tyyppiä \(\alpha\)
Tyypityssäännöt (A)
\[\begin{array}{cl} \displaystyle\frac{x:\sigma \in \Gamma}{\Gamma \vdash x:\sigma}&[\text{Var}]\\ \\ \displaystyle\frac{\Gamma \vdash e_0:\tau \rightarrow \tau' \quad\quad \Gamma \vdash e_1 : \tau } {\Gamma \vdash \text{ap}[e_0;e_1] : \tau'}&[\text{App}]\\ \\ \displaystyle\frac{\Gamma,\;x:\tau\vdash e:\ \color{red}\tau'} {\Gamma \vdash \text{lam}[x; x.e] : \tau \rightarrow {\tau'}}&[\text{Abs}]\\ \\ \displaystyle\frac{\Gamma \vdash e_0:\color{red}\sigma \quad\quad \Gamma,\,x:\color{red}{\sigma} \vdash e_1:\tau} {\Gamma \vdash \text{let}[x;e_0;x.e_1] : \tau} &[\text{Let}]\\ \\ \\ \end{array}\]
Kääntyvät melko suoraan koodiksi. Huomaa monotyyppi lambdassa ja polytyyppi letissä
Esimerkki
Näytetään, että \(\Gamma \vdash (\lambda x.x+(x+2))\ 5\ : \text{int}\), olettaen, että
- Tässä tietysti konteksissa on \(5:\text{int}\) ja
- ja sääntöihin lisätään \(\frac{\Gamma\vdash x:\text{int}\quad \Gamma\vdash y:\text{int}}{\Gamma \vdash x+y:\text{int}}\)
Eli näin:
\[\displaystyle \def\int{\text{int}} \def\fin#1{\frac{}{\displaystyle#1}} \frac{\fin{\Gamma \vdash 5 : \int} \quad \frac{\displaystyle \fin{\Gamma,x:\int\vdash x:\int}\quad\frac{\fin{\Gamma,x:\int\vdash x:\int}\quad\fin{\Gamma\vdash 2:\int}}{\displaystyle \Gamma,x:\int\ \vdash x+2:\int}[\text{plus}]}{\displaystyle\Gamma,x:\int\ \vdash x+(x+2):\int}[\text{plus}]} {\Gamma \vdash (\lambda x.x+(x+2))\ 5\ : \int} [\text{lam}]\]
Esimerkki 2
- Näytetään, että \(\text{let}\ \text{id} = \lambda x . x\ \text{in}\ \text{id} : \forall\alpha.\alpha\rightarrow\alpha\).
- (Ajattele top-level bindejä)
\[\frac{\displaystyle\frac{???}{\Gamma\vdash \lambda x.x:\forall\alpha.\alpha\rightarrow\alpha}[hmm?]\quad \fin{\Gamma,id:\forall\alpha.\alpha\rightarrow\alpha\vdash \text{id}:\forall\alpha.\alpha\rightarrow\alpha}} {\text{let}\ \text{id} = \lambda x . x\ \text{in}\ \text{id} : \forall\alpha.\alpha\rightarrow\alpha}[let]\]
"hmm?" ei ole Abs-sääntö: \[ \frac{\Gamma,\;x:\tau\vdash e:\ \tau'} {\Gamma \vdash \text{lam}[x; x.e] : \tau \rightarrow {\tau'}}[\text{Abs}]\]
Tarvitaan lisää sääntöjä:
Tyypityssäännöt (B)
\[\begin{array}{cl} \displaystyle\frac{\Gamma \vdash e:\sigma' \quad \sigma' \sqsubseteq \sigma}{\Gamma \vdash e:\sigma}&[\mathtt{Inst}]\\ \\ \displaystyle\frac{\Gamma \vdash e:\sigma \quad \alpha \notin \text{free}(\Gamma)}{\Gamma \vdash e:\forall\alpha\ .\ \sigma}&[\mathtt{Gen}]\\ \\ \end{array}\]
Vapaat muuttujat (\(\text{free}(\Gamma)\))
- Vapaa muuttuja on olennainen ja helppo käsite
- \(\forall \alpha . \alpha -> \beta\): Tässä \(\beta\) on vapaa.
- \(\forall \beta .(\forall \alpha . \alpha \rightarrow \beta)\): Tässä ei ole vapaita muuttujia.
- \(\text{int} \rightarrow \text{bool}\): Tässä \(\text{Int}\) ja \(\text{Bool}\) ovat vapaita. (Mutta varmaan sidottuja jossain ulomassa lausekkeessa)
- Samoin ympäristölle: jos \(x:\alpha \in\Gamma\), niin \(\alpha\) ei ole vapaa
Vapaat muuttujat (\(\text{free}(\Gamma)\))
- Vapaa muuttuja on olennainen ja helppo käsite
- \(\forall \alpha . \alpha -> \beta\): Tässä \(\beta\) on vapaa.
- \(\forall \beta .(\forall \alpha . \alpha \rightarrow \beta)\): Tässä ei ole vapaita muuttujia.
- \(\text{int} \rightarrow \text{bool}\): Tässä \(\text{Int}\) ja \(\text{Bool}\) ovat vapaita. (Mutta varmaan sidottuja jossain ulomassa lausekkeessa)
- Samoin ympäristölle: jos \(x:\alpha \in\Gamma\), niin \(\alpha\) ei ole vapaa
Vapaiden muuttujien löytäminen
\(\text{Free}(\alpha) = \left\{ \alpha \right\}\)
\(\text{Free}(\text{tap}[D;\tau_1; \dots; \tau_n]) = \bigcup^{n}_{i=0} \text{Free}(\tau_i)\)
\(\text{Free}(\text{forall}[\alpha;\alpha.\sigma]) = \text{Free}(\sigma) \setminus \left\{\alpha\right\}\)
(Kääntyy btw. lähes sanasta sanaan koodiksi)
Erikoistuminen (\(\sqsubseteq\))
- Ajatus lienee, että funktio \(\forall\alpha.\text{list}\ \alpha \rightarrow \alpha\) on käytettävissä myös muodossa \(\text{list}\ \text{int} \rightarrow \text{int}\).
- Tätä merkitään symbolilla "\(\sqsubseteq\)":
- Esim. \(\forall\alpha.\text{list}\ \alpha \rightarrow \alpha \sqsubseteq \text{list}\ \text{int} \rightarrow \text{int}\)
- Onko esim.
- \(\forall\alpha.\alpha \sqsubseteq \text{int}\) ?
- \(\text{int}\sqsubseteq \forall\alpha.\alpha\) ?
- \(\forall\alpha.\alpha \sqsubseteq \forall\beta.\beta\)?
- Milloin \(\alpha \sqsubseteq \beta\)?
Erikoistuminen
\(\displaystyle\frac{\tau'=[\tau/\alpha]\sigma} {\forall\alpha.\sigma \sqsubseteq \tau'}\)
\(\displaystyle\frac{\sigma\sqsubseteq\sigma'} {\forall\alpha.\sigma \sqsubseteq \forall\alpha.\sigma'}\)
\(\displaystyle\frac{\beta\notin\text{free}(\sigma)} {\forall\alpha.\sigma \sqsubseteq \forall\beta.[\beta/\alpha]\sigma}\)
Jos \(\tau'\) on saatu korvaamalla polytyypissä \(\sigma\) sidottu tyyppimuuttuja \(\alpha\) monotyypillä \(\tau\), niin \(\tau'\) on polytyypin \(\sigma\) erikoistuma.
Jos \(\forall\):n sisällä on erikoistettu, niin sekin on erikoistuma
Sidotut muuttujat saa nimetä uudestaan
Tyypityssäännöt (B)
\[\begin{array}{cl} \displaystyle\frac{\Gamma \vdash e:\sigma' \quad \sigma' \sqsubseteq \sigma}{\Gamma \vdash e:\sigma}&[\mathtt{Inst}]\\ \\ \displaystyle\frac{\Gamma \vdash e:\sigma \quad \alpha \notin \text{free}(\Gamma)}{\Gamma \vdash e:\forall\alpha\ .\ \sigma}&[\mathtt{Gen}]\\ \\ \end{array}\]
Esimerkki 2, yritys 2
- Näytetään, että \(\text{let}\ \text{id} = \lambda x . x\ \text{in}\ \text{id} : \forall\alpha.\alpha\rightarrow\alpha\).
- (Ajattele top-level bindejä)
\[\frac{\displaystyle\frac{\displaystyle\frac{\fin{\Gamma,x:\alpha\vdash x:\alpha}}{\Gamma\vdash\lambda x.x:\alpha\rightarrow\alpha}[Abs]\quad\frac{\Gamma=\emptyset}{\alpha\notin\text{free}(\Gamma)}}{\Gamma\vdash \lambda x.x:\forall\alpha.\alpha\rightarrow\alpha}[Gen]\quad \fin{\Gamma,id:\forall\alpha.\alpha\rightarrow\alpha\vdash \text{id}:\forall\alpha.\alpha\rightarrow\alpha}} {\text{let}\ \text{id} = \lambda x . x\ \text{in}\ \text{id} : \forall\alpha.\alpha\rightarrow\alpha}[let]\]
Havainto
- \(\lambda x.x\) voi yhtä hyvin olla \(\text{bool}\rightarrow\text{bool}\) tai \(\text{int}\rightarrow\text{int}\) tai \(\forall\alpha.\alpha\rightarrow\alpha\)
- Jos tehdään algoritmi, tämä täytyy päättää.
- K: Mikä valitaan?
Havainto
- V: \(\forall\alpha.\alpha\rightarrow\alpha\) tuntuu parhaalle
- Perustelu
- Huomataan, että relaatio \(\sqsubseteq\) on osittaisjärjestys (transitiivinen, reflexiivinen ja antisymmetrinen)
- Myöskin, \(\forall\alpha.\alpha\rightarrow\alpha \sqsubseteq \text{int}\rightarrow\text{int}\), mutta jos \(x \sqsubseteq\forall\alpha.\alpha\rightarrow\alpha\) niin \(x \approx \forall\alpha.\alpha\rightarrow\alpha\)
- Ts. \(\forall\alpha.\alpha\rightarrow\alpha\) on maksimaalinen yleistys/minimaalinen erikoistus termille \(\lambda x.x\)
- Näitä kutsutaan nimellä principal type ja tyypinpäättelyn pitäisi tuottaa mieluiten tälläinen.
Sitten toteutetaan
- Ideat:
- Käytetään [Gen] sääntöä
Let
muuttujan sidonnoissa - Käytetään [Inst] sääntöä muuttujan tyypityksessä
- Tehdään kaksi kierrosta AST:n yli: Kerätään rajoitteet, (ratkaistaan) ja kirjataan syntyneet tyypit paikoilleen
- Käytetään [Gen] sääntöä
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.