Luku 12 Staattinen tyyppijärjestelmä [Staattinen t]yyppijärjestelmä on ratkeava, kieliopillinen menetelmä, jota käytetään todistamaan tiettyjen käytösten puuttuminen ohjelmasta luokittelemalla ilmaisuja niiden laskemien arvojen laadun perusteella. Benjamin C. Pierce (2002, sivu 1) Tässä luvussa tarkastellaan tyyppiteoriaa, jossa on kyse staattisen tyyppijärjestelmän teoriasta. Alan tutkimuksen päätavoite on löytää vahvoja tyyppijärjestelmiä, jotka hylkäävät tyyppivirheinä yhä vähemmän käyttökelpoisia ohjelmointikonstruktioita. Täydellinen tyyppijärjestelmä on matemaattinen mahdottomuus, mutta täydellisyyttä voidaan lähestyä yhä monimutkaisempien järjestelmien avulla. Aiheen peruskirjallisuutta ovat Cardelli (2004) ja Pierce (2002). 12.1 Tyypitetty while-kieli Tarkastellaanpa while-kieltä: siinä on aritmeettiset lausekkeet ja ehtolausekkeet, sijoituslause, peräkkäistys, valintalause ja while-silmukka kuten kuvassa 12.1 on esitetty. Kielen (dynaamiseen) semantiikkaan ei tässä enää puututa, sillä se on jo käsitelty aiemmissa luvuissa. Sen sijaan määritellään sille (staattinen) tyyppijärjestelmä. Määritellään, että kielessä on kaksi tyyppiä, luvut ja totuusarvot: T, U Types T, U ::= num bool Lausekkeiden staattinen tyyppijärjestelmä tavallisesti määritellään päättelyjärjestelmänä, jossa pääteltävänä on relaatio Γ e : T, missä 121
122 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ c N x, y, z Var e, f, g Expr e, f, g ::= c true false x e e + f e f e f e = f e < f e f e f e s, t Stmt s, t ::= x := e s ; t if e then s else t while e do s Kuva 12.1: While-kielen abstrakti syntaksi Γ : Var Types on osittaisfunktio muuttujilta tyypeille, ns. tyyppiympäristö (engl. type environment) e on jokin lauseke ja T on jokin tyyppi. Relaatio Γ e : T luetaan Jos muuttujilla on ne tyypit, mitkä on Γ:ssa annettu, niin e:n tyyppi on T. Aritmeettisten operaattoreiden tyyppisäännöt ovat yksinkertaiset: operandien tulee olla lukuja ja tulos on luku: Γ e : num Γ e : num Γ e : num Γ f : num Γ e + f : num Γ e : num Γ f : num Γ e f : num Γ e : num Γ f : num Γ e f : num (12.1) (12.2) (12.3) (12.4) Vertailuoperaattoreillakin tilanne on yksinkertainen: Γ e : num Γ f : num Γ e = f : bool (12.5)
12.1. TYYPITETTY WHILE-KIELI 123 Γ e : num Γ f : num Γ e < f : bool (12.6) Samoin loogiset operaattorit: Γ e : bool Γ f : bool Γ e f : bool Γ e : bool Γ f : bool Γ e f : bool Γ e : bool Γ e : bool (12.7) (12.8) (12.9) Kaikista yksinkertaisin tilanne on vakioilla: Γ c : num Γ true : bool Γ false : bool (12.10) (12.11) (12.12) Muuttujan kohdalla joudutaan tekemään hieman lisää työtä, sillä muuttujan tyyppi täytyy etsiä tyyppiympäristöstä. Tässä yhteydessä merkintätapa Γ, x : T tarkoittaa tyyppiympäristöä, jossa x:n tyyppi on T ja joka muuten on Γ, eli Γ, x : T = Γ {(x, T): Γ, x : T x : T (12.13) Lauseiden tapaukesssa tyypitysrelaatio on Γ s jos muuttujien tyypit ovat kuten Γ:ssa, niin s on hyvin tyypitetty lause. Γ, x : T e : T Γ, x : T x := e Γ s Γ t Γ s ; t Γ e : bool Γ s Γ t Γ if e then s else t Γ e : bool Γ s Γ while e do s (12.14) (12.15) (12.16) (12.17)
124 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ Tyyppijärjestelmän soveltaminen tapahtuu rakentamalla päättelypuita: x : num x : num x : num 1 : num x : num x : num x : num 0 : num x : num x 1 : num x : num x 0 : bool x : num x := x 1 x : num while x 0 do x := x 1 Jokaiseen puun vaakaviivaan liittyy jokin yllä annetuista säännöistä. Tehtävä 2. Merkitse näkyviin, mitä sääntöä kussakin vaakaviivassa on edellä sovellettu. Yllä kuvattu while-kielen tyyppijärjestelmä on ratkeava (engl. decidable), sillä jokaisessa säännössä viivan yläpuolella on pienempiä tehtäviä kuin viivan alapuolella; ja kielioppiohjautunut (engl. syntax-directed), sillä jokaiselle (abstraktin) kieliopin produktiolle on oma sääntönsä. Nämä kaksi ominaisuutta tarkoittaa, että säännöstö on suhteellisen helppo kääntää tyyppitarkastusohjelmaksi, joko suoraan logiikkaohjelmointikieleen taikka hieman hankalammin tavanomaiseen kieleen. Kumpikin tyypitysrelaatio lausekkeiden Γ e : T ja lauseiden Γ s kääntyy omaksi aliohjelmakseen, jossa kukin ylläoleva sääntö tulee yhdeksi tapaukseksi. Tämä on esitetty listauksissa 12.1 ja 12.2 12.2 Yksinkertaisesti tyypitetty lambda-kieli Aiemmin käsitelty lambda-kieli on tyyppiteorian arkkikieli: pääosa teoreettisista tyyppijärjestelmistä on rakennettu lambda-kielen päälle. Syy tähän lienee enimmälti historiallinen, mutta on myös niin, että lambda-kieli toimii varsin mainiosti eräänlaisena kaikkien ohjelmointikielten äitinä. Tyyppiteorian perusteoria on ns. yksinkertaisesti tyypitetty (engl. simply typed) lambda-kieli Term, joka määritellään seuraavasti: x, y, z Var T, U Types T, U ::= T U t, u Term t, u ::= x tu λx : T. t
12.2. YKSINKERTAISESTI TYYPITETTY LAMBDA-KIELI 125 / Types / enum type { T_NONE / signals type error /, T_BOOL, T_NUM ; / Expressions / enum exp_kind { E_CONST, / constants / E_VAR, / variables / E_NEG, / e / E_ADD, / e+f / E_SUB, / e f / E_MUL, / e f / E_EQ, / e = f / E_NQ, / e!= f / E_LT, / e < f / E_LE, / e >= f / E_GT, / e > f / E_GE, / e >= f / E_LAND, / e && f / E_LOR / e f / ; struct exp { enum exp_kind kind; union { char variable; / E_CONST / long constant; / E_VAR / struct exp unary_operand; / E_NEG / struct { struct exp left ; struct exp right; binary_operands; / the rest / u; ; / Statements / enum stmt_kind { S_ASSIGN, S_SEQ, S_IF, S_WHILE ; struct stmt { enum stmt_kind kind; union { struct { char x; struct exp e; assign; struct { struct stmt left ; struct stmt right; seq; struct { struct exp test; struct stmt if_true; struct stmt if_false ; if_ ; struct { struct exp test; struct stmt body; while_; u; ; / Type environment ( left as an exercise for the reader ) / struct type_env; enum type lookup_var(struct type_env, const char var); / never returns T_NONE / Listaus 12.1: Tyyppitarkastusta C:llä, osa 1
126 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ / Typecheck expressions ; type error is returned as T_NONE / enum type tc_exp(struct type_env env, struct exp e) { switch (e >kind) { case E_CONST: return T_NUM; case E_VAR: { enum type ty = lookup_var(env, e >u.variable); if (ty == T_NONE) { fprintf (stderr, "undefined variable %s \n", e >u.variable); return ty; case E_NEG: if (tc_exp(env, e >u.unary_operand)!= T_NUM) { fprintf (stderr, "type error in negation\n"); return T_NONE; return T_NUM; case E_ADD: case E_SUB: case E_MUL: if (tc_exp(env, e >u.binary_operands.left)!= T_NUM tc_exp(env, e >u.binary_operands.right)!= T_NUM) { fprintf (stderr, "type error in arithmetic\n"); return T_NONE; return T_NUM; case E_EQ: case E_NQ: case E_LT: case E_LE: case E_GT: case E_GE: if (tc_exp(env, e >u.binary_operands.left)!= T_NUM tc_exp(env, e >u.binary_operands.right)!= T_NUM) { fprintf (stderr, "type error in comparison\n"); return T_NONE; return T_BOOL; case E_LAND: case E_LOR: if (tc_exp(env, e >u.binary_operands.left)!= T_BOOL tc_exp(env, e >u.binary_operands.right)!= T_BOOL) { fprintf (stderr, "type error in comparison\n"); return T_NONE; return T_BOOL; / not reached / abort (); / Typecheck statements ; returns nonzero if no type errors. / int tc_stmt(struct type_env env, struct stmt s) { switch (s >kind) { case S_ASSIGN: if (tc_exp(env, s >u.assign.e)!= lookup_var(env,s >u.assign.x)) { fprintf (stderr, "type error in assignment\n"); return 0; return 1; case S_SEQ: return tc_stmt(env, s >u.seq.left) && tc_stmt(env, s >u.seq.right); case S_IF: if (tc_exp(env, s >u.if_.test )!= T_BOOL) { fprintf (stderr, "a test must be boolean\n"); return 0; return tc_stmt(env, s >u.if_.if_true ) && tc_stmt(env, s >u.if_. if_false ); case S_WHILE: if (tc_exp(env, s >u.while_.test)!= T_BOOL) { fprintf (stderr, "a test must be boolean\n"); return 0; return tc_stmt(env, s >u.while_.body); / not reached / abort (); Listaus 12.2: Tyyppitarkastusta C:llä, osa 2
12.2. YKSINKERTAISESTI TYYPITETTY LAMBDA-KIELI 127 Vapaat muuttujat FV, korvausoperaattori [ := ] sekä α-ekivivalenssi ja β-sievennys määritellään samaan tapaan kuin tyypittömässä lambdakielessä. Tyyppisäännöt ovat seuraavat: Γ, x : T x : T Γ t : U T Γ u : U Γ tu : T Γ, x : T t : U Γ (λx : T. t) : T U (12.18) (12.19) (12.20) Huomaa, kuinka funktion parametrille on annettu tyyppi, ja huomaa, kuinka abstraktiotermin tyypityksesä parametrille annettua tyyppiä käytetään abstraktion rungon tyypityksessä laajentaen tyyppiympäristöä. Tällä tavalla määritelty yksinkertaisten tyyppien lambda-kieli on sinänsä täysin typerä, sillä yhtään tyyppiä ei ole määritelty! Senpä takia toisin kuin tyypittömässä lambda-kielessä pitää aina määritellä joitakin perustyyppejä, esimerkiksi luvut: c N x, y, z Var T, U Types T, U ::= T U Num t, u Term Num t, u ::= x tu λx : T. t c t t + u t u t u Vapaat muuttujat FV, korvausoperaattori [ := ] sekä α-ekivivalenssi määritellään samaan tapaan kuin tyypittömässä lambda-kielessä. Laskentasääntö ( ) on β-sievennyksen yleistys ja sisältää myös aritmetiikan laskemisen. Tyyppisäännöt ovat seuraavat: Γ, x : T x : T (12.21)
128 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ Γ t : U T Γ u : U Γ tu : T Γ, x : T t : U Γ (λx : T. t) : T U Γ c : Num Γ t : Num Γ t : Num Γ t : Num Γ u : Num Γ t + u : Num Γ t : Num Γ u : Num Γ t u : Num Γ t : Num Γ u : Num Γ t u : Num Tässä kielessä f (x) = x + 1 kirjoitettaisiin λx : Num. x + 1. (12.22) (12.23) (12.24) (12.25) (12.26) (12.27) (12.28) 12.3 Tyyppijärjestelmän eheys [W]ell-typed programs cannot go wrong. Milner (1978) Staattisen tyyppijärjestelmän eheydellä (engl. soundness) tarkoitetaan sitä, että se hylkää jokaisen ohjelman, joka jollakin syötteellä päätyisi dynaamiseen tyyppivirheeseen. Ehyt tyyppijärjestelmä on siten maksimaalisen vahva. Eheyden todistaminen etenee kielessä kuin kielessä seuraavasti, kunhan kielen semantiikka on määritelty lyhytaskeltekniikalla ja myös välitiloille on määritelty tyypitys: 1. Määritellään täsmällisesti, mitkä ovat semantiikan päätöstilat. 2. Huolehditaan siitä, että semantiikka jää jumiin (eli välitilaan, josta ei pääse millään säännöllä etenemään) vain ja ainoastaan tyyppivirheen sattuessa (muut virhetilanteet hoidetaan muulla tavoin). 3. Osoitetaan, että hyvin tyypitetty välitila ei koskaan jää jumiin (ns. etenemislemma). 4. Osoitetaan, että hyvin tyypitetystä välitilasta siirrytään aina hyvin tyypitettyyn tilaan (ns. säilymislemma). Näiden yhdistelmä takaa, että tyyppijärjestelmä on ehyt.
12.3. TYYPPIJÄRJESTELMÄN EHEYS 129 12.3.1 Esimerkkikieli Esimerkkinä tarkastellaan tässä yksinkertaisesti tyypitettyä lambda-kieltä laajennettuna abstraktilla perustyypillä A (joka ei sisällä yhtään lauseketta). Ensiksi syntaksi: T, U Types T, U ::= A T U Sitten vapaat muuttujat: t, u Term A t, u ::= x tu λx : T. t FV(x) = {x FV(tu) = FV(t) FV(u) FV(λx : T. t) = FV(t) \ {x Korvausoperaattori: y[x := t] = { t y jos x = y jos x = y (t 1 t 2 )[x := u] = t 1 [x := u] t 2 [x := u] λy : T. t (λy : T. t)[x := u] = λy : T.(t[x := u]) λz : T.(t[y := z][x := u]) jos x = y tai x FV(t) jos x = y ja x FV(t) ja y FV(u) jos x = y ja x FV(t) ja y FV(u) Tässä z on uusi muuttuja. Termien (α-)ekvivalenssi: λx : T. t = λy : T.(t[x := y]) t = t tu = t u u = u tu = tu t = t λx : T. t = λx : T. t y FV(t)
130 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ Sievennyssäännöt: Ja lopuksi tyypityssäännöt: (λx : T. t)u t[x := u] t t tu t u u u tu tu t t λx : T. t λx : T. t Γ, x : T x : T Γ t : U T Γ u : U Γ tu : T Γ, x : T t : U Γ (λx : T. t) : T U Määritelmä 6. Normaalimuoto on lambda-termi, joka ei sisällä β-redeksiä, eli normaalimuotoja ovat abstraktin kieliopin w ::= x wv v ::= w λx : T. v määrittelemät v:t. Kieliopin w on selkäranka (engl. spine). Lambda-kielen tapauksessa normaalimuoto on semantiikan lopputila, muut termit ovat välitiloja. Kielen ominaisuuksia todistetaan yleensä rakenneinduktiolla (engl. structural induction) eli induktiolla termin rakenteen suhteen. Tällöin todistus rakentuu paloittain niin, että jokainen kieliopin produktio käsitellään omana kohtanaan, ja produktion tarkoittama ilmaisulla todistetaan olevan haluttu ominaisuus sillä induktio-oletuksella, että produktion oikean puolen sisältämillä välikesymboleilla on myös haluttu ominaisuus. Joskus voi olla hyödyllistä jakaa myös produktion käsittely useampaan palaseen. Todistus on pätevä, jos kaikki termin muodot tulee tällä tavalla käsiteltyä. Seuraava lemma antaa tästä hyvän esimerkin: Lemma 7. Jos Γ, x : U t : T ja Γ u : U pätevät, niin Γ t[x := u] : T pätee.
12.3. TYYPPIJÄRJESTELMÄN EHEYS 131 Todistus. Induktio t:n rakenteen suhteen. Tapaus, jossa t on muuttuja, käsitellään kahdessa palassa. Samoin tapaus, jossa t on abstraktio, käsitellään kolmessa palassa Olkoon t muuttuja x. Tällöin T ja U ovat sama tyyppi, ja t[x := u] on u. Niinpä toki pätee Γ t[x := u] : T. Olkoon t jokin muuttuja y, joka ei ole x. Tällöin t[x := u] on t, ja toki pätee Γ t[x := u] : T. Olkoon t muotoa t 1 t 2. Tällöin Γ, x : U t 1 : T T ja Γ, x : U t 2 : T pätevät, ja t[x := u] on t 1 [x := u]t 2 [x := u]. Induktion nojalla pätee sekä Γ t 1 [x := u] : T T että Γ t 2 [x := u] : T. Niinpä Γ t 1 [x := u]t 2 [x := u] : T eli Γ t[x := u] : T pätee. Olkoon t muotoa λx : U. t x. Tällöin t[x := u] on t, ja toki pätee Γ t[x := u] : T. Olkoon t muotoa λy : U. t y, missä y on eri muuttuja kuin x ja y FV(y) ja x FV(u) pätevät. Tällöin Γ, y : U t y : T pätee, ja t[x := u] on λy : U.(t y [x := u]). Induktion nojalla pätee Γ, y : U t y [x := u] : T, ja niinpä pätee myös Γ λy : U.(t y [x := u]) : T eli Γ (λy : U. t y )[x := u] : T. Olkoon t muotoa λy : U. t y, missä y on eri muuttuja kuin x ja y FV(y) ja x FV(u) pätevät. Olkoon z uusi muuttuja. Tällöin Γ, y : U t y : T pätee, ja t[x := u] on λz : U.(t y [y := z][x := u]). Induktion nojalla pätee ensiksi Γ, z : U t y [y := z] : T ja toiseksi Γ, z : U t y [y := z][x := u] : T, ja niinpä pätee myös Γ λz : U.(t y [y := z][x := u]) : T eli Γ (λz : U. t y [y := z])[x := u] : T eli Γ (λy : U. t y )[x := u] : T. 12.3.2 Säilymislemma Säilymislemma tunnetaan myös nimellä subjektisievennys (engl. subject reduction). Lemma 8 (Tyyppien säilyminen). Jos Γ t : T ja t t pätevät, niin Γ t : T pätee. Todistus. Induktio t:n rakenteen suhteen. Olkoon t jokin muuttuja x. Tässä tilanteessa ei ole olemassa mitään sellaista t :a, jolla pätisi t t, joten tapaus on triviaalisti ok. Olkoon t muotoa u 1 u 2. Tällöin on olemassa tyyppi U siten, että Γ u 1 : U T ja Γ u 2 : U pätevät. On kolme tapausta: 1. t on muotoa u 1 u 2 siten, että u 1 u 1 pätee. Tällöin induktion nojalla Γ u 1 : U T pätee, ja siispä pätee myös Γ t : T.
132 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ 2. t on muotoa u 1 u 2 siten, että u 2 u 2 pätee. Tällöin induktion nojalla Γ u 2 : U pätee, ja siispä pätee myös Γ t : T. 3. u 1 on muotoa λx : U. u x. Tällöin t on muotoa u x [x := u 2 ]. Tällöin pätee Γ, x : U u x : T, ja lemman 7 nojalla pätee Γ u x [x := u 2 ] : T. Olkoon t muotoa λx : U 1. t x. Tällöin T on U 1 U 2, ja Γ, x : U 1 t x : U 2 pätee. Nyt t on muotoa λx : U. t x, missä t x t x pätee. Induktion nojalla nyt pätee Γ, x : U 1 t x : U 2, joten pätee myös Γ (λx : U 1. t x) : U 1 U 2 eli Γ t : T. 12.3.3 Etenemislemma Lemma 9 (Eteneminen). Jos Γ t : T pätee ja t ei ole normaalimuoto, niin on olemassa t siten, että t t pätee. Todistus. Induktio t:n rakenteen suhteen. Jos t on muuttuja, niin se on normaalimuoto. Olkoon t muotoa t 1 t 2. Todetaan ensin, että Γ t 1 : U T ja Γ t 2 : U pätevät jollakin U. Nyt on neljä tapausta: 1. Jos t 1 on abstraktio λx : U 1. t x, niin t :ksi kelpaa t x [x := t 2 ]. 2. Jos t 1 ei ole normaalimuoto, niin induktion nojalla on olemassa t 1 siten, että t 1 t 1 pätee. Nyt t :ksi kelpaa t 1 t 2. 3. Jos t 2 ei ole normaalimuoto, niin induktion nojala on olemassa t 2 siten, että t 2 t 2 pätee. Nyt t :ksi kelpaa t 1 t 2. 4. Jos t 1 ja t 2 ovat normaalimuotoja ja t 1 ei ole abstraktio, niin t on normaalimuoto. Jos t on muotoa λx : U 1. t x, niin Γ, x : U 1 t x : U 2 pätee ja T on U 1 U 2. Induktion nojalla on olemassa t x siten, että t x t x pätee, ja näin t :ksi kelpaa λx : U 1. t x. 12.3.4 Eheyslause Määritelmä 10. Jos termille t ei ole olemassa termiä t siten, että t t pätee, ja t ei ole normaalimuoto, niin t on jumissa (engl. stuck). Jos pätee t t ja t on jumissa, niin t on virheellinen (engl. wrong). Teoreema 11 (Yksinkertaisten tyyppien eheys). Jos termi t on virheellinen, niin t ei ole hyvin tyypitetty eli ei ole olemassa tyyppiympäristöä Γ ja tyyppiä T siten, että Γ t : T pätisi.
12.4. TYYPPIPÄÄTTELY: HINDLEY MILNER 133 Todistus. Seuraa yksinkertaisella induktiolla lemmoista 8 ja 9. 12.4 Tyyppipäättely: Hindley Milner Yksinkertaisesti tyypitetty lambda-kieli käyttää eksplisiittistä tyypitystä, jossa abstraktiomuuttujalle annetaan näkyvä tyyppi. Yleisessä käytössä on myös implisiittinen tyypitys, jossa tyyppejä ei kirjoiteta lainkaan termeihin näkyviin. Implisiittinen tapa on kielen käyttäjälle helpompi mutta vaatii taustalleen raskaampaa koneistoa (ja muuttuu tyyppijärjestelmän ilmaisuvoiman kasvaessa mahdottomaksi). Seuraavassa tarkastellaan monomorfista Hindley Milner-tyypitystä, joka on erikoistapaus Milnerin (1978) esittelemästä polymorfisesta implisiittisen tyypityksen järjestelmästä. Kieli on termien osalta samanlainen kuin tyypitön lambda-kieli: t, u Term t, u ::= x tu λxt Kielessä on kuitenkin tyyppejä, jotka ovat melkein samanlaisia kuin yksinkertaisesti tyypitetyssä lambda-kielessä: T, U Types T, U ::= α T U Nämä uudet α:t ovat tyyppimuuttujia, jotka edustavat kukin tuntematonta mutta kiinnitettyä tyyppiä: α, β, γ TyVar Vapaat muuttujat ja korvausoperaattori määritellään samalla tavalla kuin tyypittömässä lambda-kielessä, joten niiden määritelmää ei tässä toisteta. Myös kielen semantiikka on täsmälleen samanlainen kuin tyypittömässä kielessä. Homman hauskuus tulee esille vasta tyyppijärjestelmässä: {T = U Γ, x : T x : U Σ Γ t : U T Σ Γ u : U Σ Σ {U = U Γ tu : T (12.29) (12.30)
134 LUKU 12. STAATTINEN TYYPPIJÄRJESTELMÄ Σ Γ, x : α t : U Σ {T = α U Γ λxt : T α uusi (12.31) Tyypitysrelaatio Σ Γ t : T sisältää tavanomaisten tyyppiympäristön Γ, termin t ja tyypin T lisäksi myös uuden komponentin, tyyppiyhtälöryhmän Σ, joka on joukko tyyppiyhtälöitä ja joka asettaa rajoitteita T:lle. Tyypitysjärjestelmää on yksinkertaisinta käyttää siten, että käsittelee ympäristöä Γ ja termiä t syötteenä ja yhtälöryhmää Σ tuloksena. Jos halutaan tyypittää termi t ympäristössä Γ, lähdetään soveltamaan ylläolevia sääntöjä alhaalta ylöspäin relaatioon Σ Γ t : α, kuitenkin niin, että Σ rakennetaan ylhäältä alaspäin. Lopputuloksena saadaan jokin konkreettinen yhtälöryhmä Σ, josta ratkaistaan α t:n tyypiksi jos ratkaisua ei ole, tyyppiä ei ole. Esimerkkityypitys: {δ = η x : δ x : η {φ = ρ x : φ x : ρ {δ = η, β α = δ η (λxx) : β α {φ = ρ, γ = φ ρ (λxx) : γ {δ = η, β α = δ η, φ = ρ, γ = φ ρ, β = γ (λxx)(λxx) : α Yhtälöryhmä sievenee seuraavasti: β α = δ η φ = ρ δ = η γ = φ ρ β = γ δ = η β α = δ η φ = ρ β = φ ρ δ = η (φ ρ) α = δ η φ = ρ { δ = η (ρ ρ) α = δ η (ρ ρ) α = η η
12.4. TYYPPIPÄÄTTELY: HINDLEY MILNER 135 { (ρ ρ) α = η η α = η α = ρ ρ Joten (λxx)(λxx) : ρ ρ. Tällaisen yhtälöryhmän automaattinen ratkaiseminen onnistuu samastuksella.