Staattinen tyyppijärjestelmä

Samankaltaiset tiedostot
TIES542 kevät 2009 Tyyppiteorian alkeet

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Ydin-Haskell Tiivismoniste

TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia

Yksinkertaiset tyypit

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 26. kesäkuuta 2013

TIES542 kevät 2009 Rekursiiviset tyypit

14.1 Rekursio tyypitetyssä lambda-kielessä

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 16. toukokuuta 2011

Haskell ohjelmointikielen tyyppijärjestelmä

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Demo 7 ( ) Antti-Juhani Kaijanaho. 9. joulukuuta 2005

Alityypitys. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

Luku 15. Parametripolymorfismi Kumitus

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

formalismeja TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho 15. joulukuuta 2015 TIETOTEKNIIKAN LAITOS

Laajennetaan vielä Ydin-Haskellia ymmärtämään vakiomäärittelyt. Määrittely on muotoa

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Vasen johto S AB ab ab esittää jäsennyspuun kasvattamista vasemmalta alkaen:

T Syksy 2002 Tietojenkäsittelyteorian perusteet Harjoitus 8 Demonstraatiotehtävien ratkaisut

S BAB ABA A aas bba B bbs c

2.4 Normaalimuoto, pohja ja laskentajärjestys 2.4. NORMAALIMUOTO, POHJA JA LASKENTAJÄRJESTYS 13

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 19. tammikuuta 2012

uv n, v 1, ja uv i w A kaikilla

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Java-kielen perusteita

TIES542 kevät 2009 Denotaatio

TIES542 kevät 2009 Aliohjelmien formalisointia lambda-kieli

Rekursiiviset tyypit

Täydentäviä muistiinpanoja Turingin koneiden vaihtoehdoista

Insinöörimatematiikka A

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 16. marraskuuta 2015

Uusi näkökulma. TIEA341 Funktio ohjelmointi 1 Syksy 2005

vaihtoehtoja TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 13. lokakuuta 2016 TIETOTEKNIIKAN LAITOS

T Syksy 2006 Tietojenkäsittelyteorian perusteet T Harjoitus 7 Demonstraatiotehtävien ratkaisut

jäsennyksestä TIEA241 Automaatit ja kieliopit, syksy 2016 Antti-Juhani Kaijanaho 29. syyskuuta 2016 TIETOTEKNIIKAN LAITOS Kontekstittomien kielioppien

TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 2. helmikuuta 2012

Matematiikan tukikurssi, kurssikerta 3

Testaa: Vertaa pinon merkkijono syötteeseen merkki kerrallaan. Jos löytyy ero, hylkää. Jos pino tyhjenee samaan aikaan, kun syöte loppuu, niin

Turingin koneet. Sisällys. Aluksi. Turingin koneet. Turingin teesi. Aluksi. Turingin koneet. Turingin teesi

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 10. joulukuuta 2015 TIETOTEKNIIKAN LAITOS.

Laskennan mallit (syksy 2010) Harjoitus 8, ratkaisuja

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

jäsentäminen TIEA241 Automaatit ja kieliopit, syksy 2015 Antti-Juhani Kaijanaho 26. marraskuuta 2015 TIETOTEKNIIKAN LAITOS

Attribuuttikieliopit

Tyyppejä ja vähän muutakin. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Matematiikan tukikurssi, kurssikerta 2

Pinoautomaatit. Pois kontekstittomuudesta

Oliot ja tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 12. marraskuuta 2015

Pinoautomaatit. TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 6. kesäkuuta 2013 TIETOTEKNIIKAN LAITOS. Pinoautomaatit.

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 12 (opetusmoniste, kappaleet )

Lisää pysähtymisaiheisia ongelmia

(0 1) 010(0 1) Koska kieli on yksinkertainen, muodostetaan sen tunnistava epädeterministinen q 0 q 1 q 2 q3

13. Loogiset operaatiot 13.1

on rekursiivisesti numeroituva, mutta ei rekursiivinen.

Rekursiiviset palautukset [HMU 9.3.1]

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 29. toukokuuta 2013

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 8. syyskuuta 2016

13. Ratkaisu. Kirjoitetaan tehtävän DY hieman eri muodossa: = 1 + y x + ( y ) 2 (y )

T Rinnakkaiset ja hajautetut digitaaliset järjestelmät Prosessialgebra

Lisää laskentoa. TIEA341 Funktio ohjelmointi 1 Syksy 2005

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin peruskurssien laaja oppimäärä

sama tyyppi (joka vastaa kaikkien mahdollisten arvojen summa-aluetta). Esimerkiksi

Laskennan rajoja. Sisällys. Meta. Palataan torstaihin. Ratkeavuus. Meta. Universaalikoneet. Palataan torstaihin. Ratkeavuus.

Ehto- ja toistolauseet

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 12. lokakuuta 2016

M = (Q, Σ, Γ, δ, q 0, q acc, q rej )

16. Ohjelmoinnin tekniikkaa 16.1

FORMAALI SYSTEEMI (in Nutshell): aakkosto: alkeismerkkien joukko kieliopin määräämä syntaksi: sallittujen merkkijonojen rakenne, formaali kuvaus

1. Osoita, että joukon X osajoukoille A ja B on voimassa toinen ns. de Morganin laki (A B) = A B.

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 20. kesäkuuta 2013 TIETOTEKNIIKAN LAITOS.

ICS-C2000 Tietojenkäsittelyteoria. Tähän mennessä: säännölliset kielet. Säännöllisten kielten pumppauslemma M :=

Injektio (1/3) Funktio f on injektio, joss. f (x 1 ) = f (x 2 ) x 1 = x 2 x 1, x 2 D(f )

Matematiikan tukikurssi

5.5 Jäsenninkombinaattoreista

Rajoittamattomat kieliopit (Unrestricted Grammars)

ITKP102 Ohjelmointi 1 (6 op)

Luku 7. Aliohjelmat. 7.1 Kutsusekvenssit. Aliohjelma (subroutine) on useimpien kielten tärkein kontrollivuon ohjausja abstrahointikeino.

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 10. kesäkuuta 2013

7 Vapaus. 7.1 Vapauden määritelmä

1. Universaaleja laskennan malleja

Approbatur 3, demo 1, ratkaisut A sanoo: Vähintään yksi meistä on retku. Tehtävänä on päätellä, mitä tyyppiä A ja B ovat.

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä

13. Loogiset operaatiot 13.1

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

4 Matemaattinen induktio

TIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 22. toukokuuta 2013

Matematiikan tukikurssi

Chomskyn hierarkia ja yhteysherkät kieliopit

Tietotyypit ja operaattorit

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, kevät Antti-Juhani Kaijanaho. 6. maaliskuuta 2012 TIETOTEKNIIKAN LAITOS.

Ensimmäinen induktioperiaate

Tyyppipäättely. Keijo Mattila Tiivistelmä

16. Ohjelmoinnin tekniikkaa 16.1

Transkriptio:

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.